gpt4 book ai didi

c++ - 什么是 "Expression SFINAE"?

转载 作者:IT老高 更新时间:2023-10-28 13:23:45 31 4
gpt4 key购买 nike

http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx ,VC++团队正式声明他们还没有实现C++11核心特性“Expression SFINAE”。但是,以下代码示例复制自 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html被 VC++ 编译器接受。

示例 1:

template <int I> struct A {};

char xxx(int);
char xxx(float);

template <class T> A<sizeof(xxx((T)0))> f(T){}

int main()
{
f(1);
}

示例 2:

struct X {};
struct Y
{
Y(X){}
};

template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1
X f(Y, Y); // #2

X x1, x2;
X x3 = f(x1, x2); // deduction fails on #1 (cannot add X+X), calls #2

我的问题是:什么是“表达 SFINAE”?

最佳答案

我认为,您链接的论文中对表达式 SFINAE 进行了很好的解释。它是 SFINAE关于表达式。如果 decltype 中的表达式无效,那么,从重载的 VIP 休息室踢掉这个函数。您可以在此答案的末尾找到规范性措辞。

关于 VC++ 的说明:他们没有实现它完全。在简单的表达式上,它可能有效,但在其他表达式上,它不会。请参阅评论中的讨论 on this answer对于失败的例子。为简单起见,这是行不通的:

#include <iostream>

// catch-all case
void test(...)
{
std::cout << "Couldn't call\n";
}

// catch when C is a reference-to-class type and F is a member function pointer
template<class C, class F>
auto test(C c, F f) -> decltype((c.*f)(), void()) // 'C' is reference type
{
std::cout << "Could call on reference\n";
}

// catch when C is a pointer-to-class type and F is a member function pointer
template<class C, class F>
auto test(C c, F f) -> decltype((c->*f)(), void()) // 'C' is pointer type
{
std::cout << "Could call on pointer\n";
}

struct X{
void f(){}
};

int main(){
X x;
test(x, &X::f);
test(&x, &X::f);
test(42, 1337);
}

使用 Clang,这会输出预期的结果:

Could call with reference
Could call with pointer
Couldn't call

使用 MSVC,我得到...嗯,编译器错误:

1>src\main.cpp(20): error C2995: ''unknown-type' test(C,F)' : function template has already been defined1>          src\main.cpp(11) : see declaration of 'test'

It also seems that GCC 4.7.1 isn't quite up to the task:

source.cpp: In substitution of 'template decltype ((c.*f(), void())) test(C, F) [with C = X*; F = void (X::*)()]':source.cpp:29:17:   required from heresource.cpp:11:6: error: cannot apply member pointer 'f' to 'c', which is of non-class type 'X*'source.cpp: In substitution of 'template decltype ((c.*f(), void())) test(C, F) [with C = int; F = int]':source.cpp:30:16:   required from heresource.cpp:11:6: error: 'f' cannot be used as a member pointer, since it is of type 'int'

A common use of Expression SFINAE is when defining traits, like a trait to check if a class sports a certain member function:

struct has_member_begin_test{
template<class U>
static auto test(U* p) -> decltype(p->begin(), std::true_type());
template<class>
static auto test(...) -> std::false_type;
};

template<class T>
struct has_member_begin
: decltype(has_member_begin_test::test<T>(0)) {};

Live example. (令人惊讶的是,它再次适用于 GCC 4.7.1。)

另见 this answer of mine ,它在另一个环境中使用相同的技术(也就是没有特征)。


规范性措辞:

§14.8.2 [temp.deduct]

p6 At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.

p7 The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions.

p8 If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. [...]

关于c++ - 什么是 "Expression SFINAE"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12654067/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com