【问题标题】:using enable_if to specialize on return type from a base class使用 enable_if 专注于基类的返回类型
【发布时间】:2017-03-27 21:15:24
【问题描述】:

我正在将一个大型代码库移植到 clang(使用 g++ 和 intel c++ 构建)。类似于以下 sn-p 的代码在g++ 4.8 - 6.2 上编译和工作,但在clang 3.8 and 3.9 上编译失败。 MinOp 的第二次调用应该(AFAICT)获得基类专业化(“不要打电话给我!”),但 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);
}

注意,如果没有基类(MinOpBase),并且“不要打电话给我!”专业化直接在 MinOp 类中,clang works too

使用 using 语句从基类引入特化是否有效?

在我看来,这就像一堆没有太多价值的机器(当然,这已经被简化到几乎毫无意义的地步)。更好的想法?

【问题讨论】:

  • 帮助我列出要求。应该考虑三个条件?两个基本类型,两个基本类型向量和两个非基本类型向量?
  • 对我来说似乎是一个带有clang的错误。
  • @RichardHodges:不是我的代码,但我理解的要求是: 1. 我们有多种类型,包括基础(float、double)和非基础(complex、Vector、Tensor 等)浮点数、双精度数、向量的向量等)。 2. 我们有多个操作(最小值、最大值、赋值、求和等)。并非所有操作对所有类型都有意义,但我们希望通过运行时错误而不是编译或链接时来处理它。基类由许多操作共享,并列出了许多不支持这些操作的类型。我可以将这些专业复制到每个派生的...

标签: c++ templates template-specialization enable-if


【解决方案1】:

一位同事指出我的问题与 SFINAE not working on llvm/clang

我认为clang按照标准做“正确”事情的结论是正确的。来自 Johannes Schaub - litb 的回答:

7.3.3 p15 of C++11(继承函数模板的 using 声明被忽略,因为它与 a 具有相同的名称和参数 派生类的成员函数模板)

尽管其他编译器正在做可能应该是“正确”的事情。我不知道这是否已被报告为标准中的缺陷。

解决方法包括将所有特化放入基类或修改其中一种特化的参数类型之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2019-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多