模板类成员与非成员模板函数的歧义

时间:2019-01-26 12:07:08

标签: c++ templates operator-overloading overload-resolution template-classes

我正在开发用于自动/算法区分的仅标头库。目的是能够简单地更改输入给函数的变量的类型并计算一阶和二阶导数。为此,我创建了一个模板类,使程序员可以选择私有数据成员的存储类型。下面包含一个带有令人讨厌的运算符重载的代码段。

template <typename storage_t>
class HyperDual
{
    template <typename T> friend class HyperDual;
    public:
        template <typename T>
        HyperDual<storage_t> operator+(const HyperDual<T>& rhs) const
        {
            HyperDual<storage_t> sum;
            for (size_t i = 0; i < this->values.size(); i++)
                sum.values[i] = this->values[i] + rhs.values[i];
            return sum;
        }
    protected:
        std::vector<storage_t> values;
};

稍后,为了最大限度地提高多功能性,我提供了允许交互的模板功能。

template <typename storage_t, typename T>
HyperDual<storage_t> operator+(const HyperDual<storage_t>& lhs, const T& rhs)
{
    static_assert(std::is_arithmetic<T>::value && !(std::is_same<T, char>::value), "RHS must be numeric");
    return HyperDual<storage_t>(lhs.values[0] + rhs);
}

template <typename storage_t, typename T>
HyperDual<storage_t> operator+(const T& lhs, const HyperDual<storage_t>& rhs)
{
    static_assert(std::is_arithmetic<T>::value && !(std::is_same<T, char>::value), "LHS must be numeric");
    return HyperDual<storage_t>(lhs + rhs.values[0]);
}

我遇到的是编译器试图实例化第二个非成员模板函数。

#include "hyperspace.h"

int main()
{
    HyperDual<long double> one(1); // There is an appropriate constructor
    HyperDual<double> two(2);

    one + two;

    return 0;
}

为此,我收到static_assert生成的错误“ LHS必须为数字”。我该如何解决歧义?

2 个答案:

答案 0 :(得分:0)

使用enable_if_t来使非成员模板只能在特定的上下文中应用?

template <typename storage_t, typename T, typename = enable_if_t<std::is_arithmetic<T>::value && !(std::is_same<T, char>::value)>>
HyperDual<storage_t> operator+(const HyperDual<storage_t>& lhs, const T& rhs)
{
    static_assert(std::is_arithmetic<T>::value && !(std::is_same<T, char>::value), "RHS must be numeric");
    return HyperDual<storage_t>(lhs.values[0] + rhs);
}

static_assert可能在此处重复。

答案 1 :(得分:0)

好的。我发现了自己的问题。归结为static_assert和std :: enable_if

之间的区别

替换我的模板声明并删除static_assert,我实现了等效的功能:

template <typename storage_t, typename T,
          typename = typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, char>::value>::type>
HyperDual<storage_t> operator+(const T& lhs, const HyperDual<storage_t>& rhs)
{
    return HyperDual<storage_t>(lhs + rhs.value());
}

(细节小,但rhs.values[0]rhs.value()取代。这与模板问题无关,但与成员访问权限有关。