code

"식 SFINAE"는 무엇입니까?

codestyles 2020. 12. 31. 08:19
반응형

"식 SFINAE"는 무엇입니까?


에서 http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx 의 VC ++ 팀은 공식적으로 아직 C ++ 11의 핵심 기능 "표현 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

제 질문은 "Expression SFINAE"가 무엇인가요?


당신이 연결 한 논문에서 SFINAE 표현이 꽤 잘 설명되어 있다고 생각합니다. 그것은이다 SFINAE을 표현식. 내부 표현 decltype이 유효하지 않다면 VIP 라운지에서 과부하가 걸린 함수를 시작하십시오. 이 답변의 끝에서 규범적인 표현을 찾을 수 있습니다.

VC ++에 대한 참고 : 그들은 그것을 완전히 구현하지 않았습니다 . 단순한 표현에서는 작동 할 수 있지만 다른 표현에서는 작동하지 않습니다. 실패한 예는 이 답변에 대한 의견의 토론을 참조하십시오 . 간단하게하기 위해 이것은 작동하지 않습니다.

#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을 사용하면 예상되는 결과가 출력됩니다.

참조로
호출 할 수 있음 포인터로 호출 할 수 있음 호출
할 수 없음

MSVC를 사용하면 ... 음, 컴파일러 오류가 발생합니다.

1> src \ main.cpp (20) : 오류 C2995 : ''unknown-type 'test (C, F)': 함수 템플릿이 이미 정의되었습니다.
1> src \ main.cpp (11) : 'test'선언 참조

또한 GCC 4.7.1이 작업에 적합하지 않은 것 같습니다.

source.cpp : 'template decltype ((c. * f (), void ())) test (C, F) [with C = X *; F = 무효 (X :: *) ()] ':
source.cpp:29:17:   required from here
source.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 here
source.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. (Which, surprisingly, works again on GCC 4.7.1.)

See also this answer of mine, which uses the same technique in another environment (aka without traits).


Normative wording:

§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. [...]

ReferenceURL : https://stackoverflow.com/questions/12654067/what-is-expression-sfinae

반응형