1 回答

TA貢獻1828條經驗 獲得超3個贊
我認為,您所鏈接的論文中對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:“未知類型” test(C,F)':功能模板已經定義
1> src \ main.cpp(11):參見'test'的聲明
似乎GCC 4.7.1還不能完全完成任務:
source.cpp:代替'模板decltype((c。* f(),void()))test(C,F)[C = X *; F =無效(X :: *)()]':
source.cpp:29:17:從這里需要
source.cpp:11:6:錯誤:無法將成員指針'f'應用于非類類型'X *'的'c'
source.cpp:代替'template decltype((c。* f(),void()))test(C,F)[C = int; F = int]':
source.cpp:30:16:從這里需要
source.cpp:11:6:錯誤:'f'不能用作成員指針,因為它的類型為'int'
表達式SFINAE的常見用法是在定義特征時,例如用于檢查類是否具有某個成員函數的特征:
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)) {};
現場示例。(令人驚訝的是,這再次適用于GCC 4.7.1。)
另請參閱我的答案,該答案在另一種環境(也稱為無特征)中使用相同的技術。
規范用語:
§14.8.2 [temp.deduct]
p6 在模板自變量推導過程中的某些點,必須采用利用模板參數的函數類型,并用相應的模板自變量替換這些模板參數。當將任何顯式指定的模板參數替換為函數類型時,此操作在模板參數推論的開始時進行;當替換從默認參數推論或獲得的任何模板參數時,在模板參數推論的末尾再次進行。
p7 替換發生在函數類型和模板參數聲明中使用的所有類型和表達式中。表達式不僅包括常量表達式(例如出現在數組范圍內或作為非類型模板參數的常量表達式),而且還包括,和內部 允許非常量表達式的其他通用表達式(即,非常量表達式)。sizeofdecltype
p8如果替換導致無效的類型或表達式,則類型推導失敗。無效的類型或表達式是使用替換參數編寫的格式或表達式。[...]
- 1 回答
- 0 關注
- 457 瀏覽
添加回答
舉報