【问题标题】:Template class member vs. non-member template function ambiguity模板类成员与非成员模板函数的歧义
【发布时间】:2019-01-26 12:07:07
【问题描述】:

我正在开发一个仅用于自动/算法区分的标头库。目标是能够简单地更改输入函数的变量类型并计算一阶和二阶导数。为此,我创建了一个模板类,允许程序员选择私有数据成员的存储类型。下面是一个带有违规运算符重载的 sn-p。

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 必须是数字”。我将如何解决歧义?

【问题讨论】:

  • 您提供了operator+=,但您从未声明过operator+(HyperDual&lt;U&gt;, HyperDual&lt;V&gt;),您可能需要声明它。 operator+=不会免费给你operator+
  • 如果两个操作数都是HyperDual,大概你应该想提供一个单独的operator+,不是吗?
  • 我从我的代码中复制了错误的函数。它应该是成员 operator+ 函数。问题已更新为正确的功能。

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


【解决方案1】:

使用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 可能在此处重复。

【讨论】:

    【解决方案2】:

    好的。我发现了我自己的问题。归结为 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()。这和模板问题无关,但和会员访问有关。

    【讨论】:

      猜你喜欢
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 2020-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多