c – sfinae与decltype:cl ang或gcc?

前端之家收集整理的这篇文章主要介绍了c – sfinae与decltype:cl ang或gcc?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
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.

给出的示例描述了模板定义中的形式不正确的表达“可以在模板定义中或在实例化点被诊断.

默认的template-argument(14.1p9)U = decltype(tf(1))在struct outer的实例化的上下文中是一个非依赖的名称(也就是说,它不依赖于自己模板的模板参数)所以使用T = struct为空的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); }
原文链接:https://www.f2er.com/c/116177.html

猜你在找的C&C++相关文章