【问题标题】:template argument deduction/substitution in operator运算符中的模板参数推导/替换
【发布时间】:2016-08-12 17:21:14
【问题描述】:

我有一组从一个基派生的类:

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;

现在我想重载使用我的派生类的operator+ (3=1+2):

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。正如我所说,我还需要重载 + 运算符。

【问题讨论】:

  • 提供完整的自包含测试用例
  • shared_ptr&lt;Derived&gt; 不是 shared_ptr&lt;Base&gt;,尽管您可以隐式地从一个转换为另一个。

标签: c++ templates gcc operator-overloading


【解决方案1】:

这里的问题是编译器无法通过尝试将参数类型std::shared_ptr&lt;Pover_of_Number&lt;TraitsExample&gt;&gt; 与参数类型std::shared_ptr&lt;Base&lt;Traits&gt;&gt; 进行匹配来推断Traits。从 first 到 std::shared_ptr&lt;Base&lt;TraitsExample&gt;&gt; 的转换涉及隐式转换,因此不能自动进行扣除。

我会在您的 Base&lt;Traits&gt; 类中添加一个公共 typedef 并使用它来确定 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 成员的任何内容。

Full demo.

【讨论】:

    猜你喜欢
    • 2015-07-22
    • 1970-01-01
    • 2015-07-12
    • 2018-04-28
    • 2014-09-22
    • 2020-12-14
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    相关资源
    最近更新 更多