我有一组派生自一个基类的类:
template<typename Traits>
class Base{
typedef typename Traits::scalar_t scalar_t;
public:
virtual ~Base(){}
virtual scalar_t apply(const scalar_t&) const=0;
};
template<typename Traits>
class Pover_of_Number:
public Base<Traits>{
typedef typename Traits::scalar_t scalar_t;
public:
Pover_of_Number(const scalar_t& power):
power(power){}
scalar_t apply(const scalar_t& value) const override{
return pow(value,power);
}
private:
scalar_t power;
};
template<typename Traits>
class Mult_by_Number:
public Base<Traits>{
typedef typename Traits::scalar_t scalar_t;
public:
Mult_by_Number(const scalar_t& num):
num(num){}
scalar_t apply(const scalar_t& value) const override{
return num*value;
}
private:
scalar_t num;
};
template<typename Traits>
class SumOperator:
public Base<Traits>{
typedef Base<Traits> BT;
typedef typename Traits::scalar_t scalar_t;
public:
SumOperator(const std::shared_ptr<Base<Traits>>& op1,
const std::shared_ptr<Base<Traits>>& op2):
op1{op1}, op2{op2}{}
scalar_t apply(const scalar_t& value) const override{
return op1->apply(value)+op2->apply(value);
}
private:
std::shared_ptr<BT> op1;
std::shared_ptr<BT> op2;
};
对于某些特定的Traits
,此代码可以完美运行:
class TraitsExample{
public:
typedef double scalar_t;
};
int main(){
auto op1=std::make_shared<Pover_of_Number<TraitsExample>>(2.);
auto op2=std::make_shared<Mult_by_Number<TraitsExample>>(10.);
//works correctly
auto sumop=std::make_shared<SumOperator<TraitsExample>>(op1,op2);
std::cout<<sumop->apply(2.)<<std::endl;
现在我想重载使用我的派生类(3 = 1 + 2)的operator+
:
template<typename Traits>
std::shared_ptr<SumOperator<Traits>> operator+(
const std::shared_ptr<Base<Traits>>& op1,
const std::shared_ptr<Base<Traits>>& op2){
return std::make_shared<SumOperator<Traits>>(op1,op2);
}
但是当我在代码中使用它时出现template argument deduction/substitution failed
错误。
有人可以向我解释为了让gcc编译我的代码需要做些什么,最好不要使用任何额外的类来进行演绎。
PS:人们可以找到工作example。正如我所说,我还需要重载+
运算符。
答案 0 :(得分:0)
此处的问题是编译器无法推断Traits
尝试将参数类型std::shared_ptr<Pover_of_Number<TraitsExample>>
与参数类型std::shared_ptr<Base<Traits>>
匹配。从第一个转换为std::shared_ptr<Base<TraitsExample>>
涉及隐式转换,因此扣除不会自动发生。
我会在您的typedef
课程中添加公开Base<Traits>
并使用它来确定operator+
的返回类型应该是什么:
#include <type_traits>
template<typename Traits>
class Base{
typedef typename Traits::scalar_t scalar_t;
public:
using traits_type = Traits;
virtual ~Base(){}
virtual scalar_t apply(const scalar_t&) const=0;
};
template<typename T, typename U>
std::enable_if_t<std::is_same<typename T::traits_type, typename U::traits_type>::value,
std::shared_ptr<SumOperator<typename T::traits_type>>> operator+(
const std::shared_ptr<T>& op1,
const std::shared_ptr<U>& op2){
return std::make_shared<SumOperator<typename T::traits_type>>(op1,op2);
}
请注意,由于SFINAE,如果没有operator+
成员,此traits_type
将无法正确匹配任何内容。