【问题标题】:Specialize same operator for different traits为不同的特征专门化相同的运算符
【发布时间】:2017-01-22 16:17:21
【问题描述】:

我想通过特质专业化来做以下事情。

  1. Array Aa = Scalar in_a 将使用overload I

  2. Array Aa = Array Bb 将使用overload II

在下面的代码中,overload II 永远不会被使用。

有人提到T1不能在overload II中推导出来。

如何解决?

我使用 C++ shell 用 C++14 编译代码。

#include <iostream>
#include <type_traits>

using namespace std;
class A; // forward declaration.

template <typename T>
struct is_A : false_type {};
template <> struct is_A<A> : true_type {};

template <typename T>
struct is_int : false_type {};
template <> struct is_int<int> : true_type {};
template <> struct is_int<long> : true_type {};

class A{
    public:
        int val;
        void print(void){
            std::cout << val << std::endl;
        }
        template <typename T1>
        enable_if_t<is_int<T1>::value,void>
        operator=(const T1 & input){
            val = 2*input; //Overload I
        }
        template <typename T1>
        enable_if_t<is_A<T1>::value,void>
        operator=(const T1 & Bb){
            val = 5*Bb.val; //Overload II
        }
};

int main(void){
    A Aa;
    A Bb;
    int in_a = 3;
    Aa = in_a; //This uses overload I as intended.
    Bb = Aa; //I want this to use overload II, but
             //actually overload I is used.
             //This leads to an error during compilation.
    Aa.print(); //This should give 6. (3x2)
    Bb.print(); //This should give 30. (6x5)
}

【问题讨论】:

  • 你有operator=(A &amp; Bb) 没有T1...但是在你的情况下,简单的重载似乎就足够了。
  • operator = 应该返回 A&amp; 并采用 const 引用。
  • 这是固定的(希望是正确的)。但是现在编译器又报错了。
  • enable_if 也应该是 enable_if_t

标签: c++ c++14 template-specialization typetraits


【解决方案1】:

这是您的代码简化并按预期工作:

#include <iostream>
#include <type_traits>
#include<utility>

class A;

template <typename T>
struct is_A : std::false_type {};
template <> struct is_A<A> : std::true_type {};

template <typename T>
struct is_int : std::false_type {};
template <> struct is_int<int> : std::true_type {};
template <> struct is_int<long> : std::true_type {};

class A{
public:
    int val;

    void print(void){
        std::cout << val << std::endl;
    }

    template <typename T1>
    std::enable_if_t<is_int<std::decay_t<T1>>::value, void>
    operator=(T1 && input){
        val = 2*std::forward<T1>(input);
    }

    template <typename T1>
    std::enable_if_t<is_A<std::decay_t<T1>>::value,void>
    operator=(T1 && Bb){
        val = 5*std::forward<T1>(Bb).val;
    }
};

int main(void){
    A Aa;
    A Bb;
    int in_a = 3;
    Aa = in_a;
    Bb = Aa;
    Aa.print(); //This should give 6. (3x2)
    Bb.print(); //This should give 30. (6x5)
}

【讨论】:

  • 感谢您的回答。我需要定义自己的特征,is_same 不起作用。我正在为此发布另一个问题。
  • @rxu 好吧,答案仍然适用。使用你自己的特质,它也会起作用。
  • 实际情况是 float、int、short 等将被视为标量。矩阵类型 A、矩阵类型 B、矩阵类型 C 将被视为 is_A... 我有一个古老的标准库。我只能从最新的标准库中复制一些东西。
  • 我想我下次简化代码时会评论简化的内容……我的错。
  • '' 正在寻找 decay'' 的实现
【解决方案2】:

你的代码应该是

template <typename T>
std::enable_if_t<is_int<T>::value, A&>
operator=(const T& input){
    val = 2 * input; //Overload I
    return *this;
}
template <typename T>
std::enable_if_t<is_A<T>::value, A&>
operator=(T& rhs){
    val = 5 * rhs.val; //Overload II
    return *this;
}

Demo

但在你的情况下更简单

A& operator=(int input){
    val = 2 * input; //Overload I
    return *this;
}

A& operator=(const A& rhs){
    val = 5 * rhs.val; //Overload II
    return *this;
}

【讨论】:

  • 我绝对需要enable_if_t,因为该代码是实际代码的简化版本。非常感谢您的回答。我将在实际代码上对其进行测试。
  • 这里是c++ shell中的编译结果。 cpp.sh/2xuum ... error: 'enable_if_t' in namespace 'std' does not name a template type
  • 如果为 c++14 编译,运行编译后的程序会得到 6 6 而不是 6 30cpp.sh/5jpn
  • 复制分配不应该是模板,你必须添加A&amp; operator=(const A&amp;)
  • @skypjack:确实,这不是必需的,但这是一种很好的做法。因为operator == 可能会返回std::string 而不是预期的bool
【解决方案3】:

对于您的简单案例,您真的需要所有的模板魔法吗?

#include <iostream>

class A;

class A{
public:
    int val;

    void print(void){
        std::cout << val << std::endl;
    }

    void operator =(const A& in){ val = in.val*5; }
    void operator =(int in) { val = in*2; }
};


int main(void){
    A Aa;
    A Bb;
    Aa = 3;
    Bb = Aa;
    Aa.print(); //This should give 6. (3x2)
    Bb.print(); //This should give 30. (6x5)
    return 0;
}

【讨论】:

  • 这是简化的代码。我需要实际代码的模板和特性化。有许多类型的数组用于 int、float、double 等以及许多类型的标量。需要他们之间的数学模板。
  • 有可能。但是,很难从代码的和平中理解整个问题。你的意思是像向量求和、乘法等数学吗?像在 matlab 中一样?
  • 是的。数学就像在 python 的 numpy 库中一样,在 matlab 中也是如此。
  • 这对我来说很有趣,因为前段时间我做了一个基于模板的矩阵数学库。如果您将使用模板,那么您可以删除循环。我的意思是,如果您使用向量元素运算,例如两个向量 (Vector) 的总和,则不需要在内部执行循环“for(int i = 0; i
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 2015-10-29
  • 2015-12-04
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
相关资源
最近更新 更多