模板 class 成员与 non-member 模板函数歧义
Template class member vs. non-member template function ambiguity
我正在为 automatic/algorithmic 差异化开发一个 header-only 库。目标是能够简单地更改输入函数的变量类型并计算一阶和二阶导数。为此,我创建了一个模板 class,允许程序员 select 私有数据成员的存储类型。下面是一个带有违规运算符重载的片段。
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]);
}
我遇到的是编译器正在尝试实例化第二个 non-member 模板函数。
#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 must be numeric"。我将如何解决歧义?
使用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
可能在此处重复。
好的。我发现了我自己的问题。归结为 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()
。这个和模板问题无关,但是和成员权限有关。
我正在为 automatic/algorithmic 差异化开发一个 header-only 库。目标是能够简单地更改输入函数的变量类型并计算一阶和二阶导数。为此,我创建了一个模板 class,允许程序员 select 私有数据成员的存储类型。下面是一个带有违规运算符重载的片段。
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]);
}
我遇到的是编译器正在尝试实例化第二个 non-member 模板函数。
#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 must be numeric"。我将如何解决歧义?
使用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
可能在此处重复。
好的。我发现了我自己的问题。归结为 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()
。这个和模板问题无关,但是和成员权限有关。