使用 enable_if 专注于基于 class 的 return 类型
using enable_if to specialize on return type from a base class
我正在将一个大型代码库移植到 clang(使用 g++ 和 intel c++ 构建)。类似于以下代码片段的代码可以在 g++ 4.8 - 6.2 but fails to compile with clang 3.8 and 3.9 上编译和运行。第二次调用 MinOp 应该 (AFAICT) 获得基础 class 专业化 ("Don't call me!"),但 clang 尝试实例化 std::min 版本并失败:
#include <algorithm>
#include <iostream>
#include <type_traits>
template <typename T> class Vector
{
public:
Vector() : xyz{} {}
Vector(T const &x, T const &y, T const &z) : xyz{y, y, z} {}
Vector<T> min(Vector<T> const &v) { return Vector<T>(std::min(xyz[0], v.xyz[0]), std::min(xyz[1], v.xyz[1]), std::min(xyz[2], v.xyz[2])); }
T xyz[3];
};
class MinOpBase
{
public:
template <class T> typename std::enable_if<!std::is_fundamental<T>::value>::type
operator()(Vector<T> &left, Vector<T> const &right) const { std::cout << "Don't call me!" << std::endl; }
};
class MinOp : public MinOpBase
{
public:
template <typename T> void operator()(T &left, T const &right) const
{ left = std::min(left, right); }
// Support component-wise min on vectors of fundamental types
template <typename T> typename std::enable_if<std::is_fundamental<T>::value>::type
operator() (Vector<T> &left, Vector<T> const &right) const
{ left.min(right); }
using MinOpBase::operator();
};
int main()
{
Vector<double> v1, v2;
Vector<Vector<double>> vv1, vv2;
MinOp m;
m(v1,v2);
m(vv1,vv2);
}
注意如果没有基础class(MinOpBase),"Don't call me!"特化直接在MinOpclass,clang works too.
这种使用 using 语句从基础引入特化的方法是否有效?class
在我看来,这就像一大堆没有太大价值的机器(当然,这已经被简化到几乎毫无意义的地步)。更好的想法?
一位同事指出我的问题与
SFINAE not working on llvm/clang
我认为 clang 正在按照标准做 "right" 事情的结论是正确的。来自 Johannes Schaub - litb 的回答:
7.3.3 p15 of C++11 (the using declaration of the inherited function template is ignored because it has the same name and parameters as a
member function template of the derived class)
虽然其他编译器正在做可能应该是 "right" 的事情。我不知道这是否已被报告为标准中的缺陷。
变通方法包括将所有特化放入基础 类 或修改其中一个特化的参数类型之一。
我正在将一个大型代码库移植到 clang(使用 g++ 和 intel c++ 构建)。类似于以下代码片段的代码可以在 g++ 4.8 - 6.2 but fails to compile with clang 3.8 and 3.9 上编译和运行。第二次调用 MinOp 应该 (AFAICT) 获得基础 class 专业化 ("Don't call me!"),但 clang 尝试实例化 std::min 版本并失败:
#include <algorithm>
#include <iostream>
#include <type_traits>
template <typename T> class Vector
{
public:
Vector() : xyz{} {}
Vector(T const &x, T const &y, T const &z) : xyz{y, y, z} {}
Vector<T> min(Vector<T> const &v) { return Vector<T>(std::min(xyz[0], v.xyz[0]), std::min(xyz[1], v.xyz[1]), std::min(xyz[2], v.xyz[2])); }
T xyz[3];
};
class MinOpBase
{
public:
template <class T> typename std::enable_if<!std::is_fundamental<T>::value>::type
operator()(Vector<T> &left, Vector<T> const &right) const { std::cout << "Don't call me!" << std::endl; }
};
class MinOp : public MinOpBase
{
public:
template <typename T> void operator()(T &left, T const &right) const
{ left = std::min(left, right); }
// Support component-wise min on vectors of fundamental types
template <typename T> typename std::enable_if<std::is_fundamental<T>::value>::type
operator() (Vector<T> &left, Vector<T> const &right) const
{ left.min(right); }
using MinOpBase::operator();
};
int main()
{
Vector<double> v1, v2;
Vector<Vector<double>> vv1, vv2;
MinOp m;
m(v1,v2);
m(vv1,vv2);
}
注意如果没有基础class(MinOpBase),"Don't call me!"特化直接在MinOpclass,clang works too.
这种使用 using 语句从基础引入特化的方法是否有效?class
在我看来,这就像一大堆没有太大价值的机器(当然,这已经被简化到几乎毫无意义的地步)。更好的想法?
一位同事指出我的问题与 SFINAE not working on llvm/clang
我认为 clang 正在按照标准做 "right" 事情的结论是正确的。来自 Johannes Schaub - litb 的回答:
7.3.3 p15 of C++11 (the using declaration of the inherited function template is ignored because it has the same name and parameters as a member function template of the derived class)
虽然其他编译器正在做可能应该是 "right" 的事情。我不知道这是否已被报告为标准中的缺陷。
变通方法包括将所有特化放入基础 类 或修改其中一个特化的参数类型之一。