c++ - 带有 decltype : bug in clang or gcc? 的 sfinae

标签 c++ gcc c++11 clang sfinae

Clang-3.2 可以编译并且代码按预期运行:

struct have_f { int f(int i) {return 10;} }; 

struct empty {};

template <class T> 
struct outer {
        T t; 

        // if T have f(), define  outer_f()
        template<class U=decltype(t.f(1))> 
        int outer_f(int i) { return t.f(i); }
};

int main() {
        outer<have_f>  o1;
        outer<empty>   o2;

        // to silence unused var warning
        return  o1.outer_f(10) + sizeof(o2); 
}

任何版本的 GCC 拒绝:

t.cc:13:6: error: ‘struct empty’ has no member named ‘f’
  int outer_f(int i) { return t.f(i); }
      ^

谁是对的? Gcc 还是 Clang?

请注意,有 similar question ,没有真正的答案。

最佳答案

我认为问题出在 14.6.3 [temp.nondep]:

1 - Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used.

给出的示例描述了模板定义中格式错误的表达式“可以[在模板定义中]或在实例化时诊断”。

默认模板参数 (14.1p9) U=decltype(t.f(1))struct outer 实例化上下文中的非依赖名称(也就是说,它不依赖于它自己模板的模板参数)所以它对于 struct outer 的实例化是错误的与 T = struct empty .该标准没有明确描述默认模板参数的评估位置,但唯一明智的结论是它们被视为任何其他构造并在它们出现的时候进行评估(或者,在这个例子中,在struct outer 模板)。我看不到编译器有任何余地可以将非依赖默认模板参数的评估延迟到适用 SFINAE 的上下文。

幸运的是解决方案很简单:只需将默认模板参数设置为 U依赖名称:

    // if T have f(), define  outer_f()
    template<class T2 = T, class U=decltype(static_cast<T2 &>(t).f(1))> 
    int outer_f(int i) { return t.f(i); }

关于c++ - 带有 decltype : bug in clang or gcc? 的 sfinae,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12813351/

相关文章:

c++ - 使用模板访问成员变量

c++ - 使用 linux 操作内存中的位图图像

c++ - 使用 iomanip 将数据输出格式化为带有 Qt 的文本文件

c++ - boost::interprocess_mutex 与 Win32 native 互斥锁的性能如何?

c++ - 引用在函数范围内定义的类

c++ - GCC 中的 std::put_time 实现状态?

c++ - 如何正确地将 OpenCV 库链接到 Windows 上的 Eclipse?

c++ - 为什么 C++0x 中的 Lambda 函数返回类型必须是自动的?

c - 未定义对 `shm_open' 的引用,即使在使用 -pthread -lrt 进行编译时也是如此

c++ - 遍历类模板的显式特化