C++ C++;动态检测参数类并将其转换为
我有两个类,一个继承自另一个。基类的相关部分如下所示(很明显,这个类有ctor、dtor等,特别是C++ C++;动态检测参数类并将其转换为,c++,c++11,operator-overloading,C++,C++11,Operator Overloading,我有两个类,一个继承自另一个。基类的相关部分如下所示(很明显,这个类有ctor、dtor等,特别是操作符[],但我认为这些与手头的问题无关): #包括 模板 类向量 { 公众: 模板友元向量运算符+(常量向量&,常量向量&); 模板friend std::ostream&operator&); }; 派生类(同样,显然我已经去掉了那些我认为不相关的部分): #包括“Vector.h” 模板 类多项式 :公共向量 { 公众: 模板friend std::ostream&operator&); }
操作符[]
,但我认为这些与手头的问题无关):
#包括
模板
类向量
{
公众:
模板友元向量运算符+(常量向量&,常量向量&);
模板friend std::ostream&operator&);
};
派生类(同样,显然我已经去掉了那些我认为不相关的部分):
#包括“Vector.h”
模板
类多项式
:公共向量
{
公众:
模板friend std::ostream&operator&);
};
(注意:friend函数在模板中使用的字母与类不同,因为gcc在其他情况下会抱怨“隐藏”。不过,逻辑是相同的。)
Vector
s单向打印(例如<3,5,1>
)<代码>多项式s打印另一个(例如3x^2+5x+1
)
不过,这会引起一个问题。当我将两个多项式
s相加时,编译器使用模板Vector操作符+(const Vector&,const Vector&)
,它当然返回一个向量
。因此,如果我尝试执行类似std::cout Vector操作符+(const Vector&,const Vector&)
这样的操作,它将检测其参数的实际数据类型,并相应地转换返回值(例如,如果向其传递两个多项式,则返回一个多项式。如果可能的话,我想这样做,而不需要操作符+
了解向量的每个可能的子类(我认为这可能是一个合理的愿望?),也不需要为每个子类创建新的操作符+
函数(因为我还有其他几个重载运算符,并且希望避免为每个派生类复制几乎完全相同的代码十次)
< P>我知道Python中这是可能的(事实上比较容易)。C++支持这样的事情吗?< /P> < P>如果计算结果为<代码>向量< /代码>,你不能简单地(合法地)将其转换为多项式
。为了达到预期效果,您需要一些更深入的修改。您需要一个免费的运算符+
,一个可以提供预期结果类型的实现,以及一种检测从向量
派生的所有内容的方法。让我们构建它
a) 检测所有向量
为此,您可以从空基类派生,该空基类将通过空基类优化(EBO)进行优化,如果std::enable\u
:
struct VectorBase {};
template< class T, unsigned int N >
class Vector
{
// ...
};
应替换为:
template< class T, unsigned int N >
class Vector
{
friend Vector< T, N > operator+ ( const Vector< T, N >&, const Vector< T, N >& );
};
减去一些小的打字错误(我还没有测试过),这个策略应该适合你。谢谢你的回答!我在这里看到了一些我不熟悉的代码,所以我会做一些研究。@Arandur:我承认这是非常先进的,但我看不到更简单的方法。另外,请注意,代码使用了C++11功能,因此您需要一个支持它的编译器,并且通常还需要显式启用C++11。好吧,这是一个非常神奇的功能,但它的工作方式很有魅力!再次感谢你的回答。是的,我一直在使用C++11的特性,所以这对我来说很有用。谢谢
struct VectorBase {};
template< class T, unsigned int N >
class Vector
{
// ...
};
template< class T, unsigned int N >
class Vector
{
template < class U, unsigned int M >
friend Vector< U, M > operator+ ( const Vector< U, M >&, const Vector< U, M >& );
};
template< class T, unsigned int N >
class Vector
{
friend Vector< T, N > operator+ ( const Vector< T, N >&, const Vector< T, N >& );
};
template< class T, unsigned int N >
class Vector
{
public:
template< typename R >
static R add( const Vector< T, N >& lhs, const Vector< T, N >& rhs )
{
static_assert( std::is_base_of<VectorBase,R>::value,
"R needs to be derived from Vector<T,N>" );
R result;
// implement it here...
return result;
}
};
// as a free function:
template< typename V >
typename std::enable_if< std::is_base_of< VectorBase, V >::value, V >::type
operator+( const V& lhs, const V& rhs )
{
return V::template add<V>( lhs, rhs );
}