SFINAE 技術(shù)窒悔,即匹配失敗不是錯誤阶界,英文Substitution Failure Is Not An Error,其作用是當(dāng)我們在進行模板特化的時候氧映,會去選擇那個正確的模板,避免失敗
看個具體的例子:
long multiply(int i, int j) { return i * j; }
template <class T>
typename T::multiplication_result multiply(T t1, T t2)
{
return t1 * t2;
}
int main(void)
{
multiply(4,5);
}
當(dāng)我們編譯的時候臼疫,會去匹配模板 multiply,但是由于我們不知道m(xù)ultiplication_result,根據(jù) Substitution Failure Is Not An Error 富蓄,于是我們就去選擇函數(shù) multiply
這種技術(shù)在代碼中的一個大的用途就是在編譯時期來確定某個 type 是否具有我們需要的性質(zhì),看代碼
template <class T>
struct is_pointer
{
template <class U>
static char is_ptr(U *);
template <class X, class Y>
static char is_ptr(Y X::*);
template <class U>
static char is_ptr(U (*)());
static double is_ptr(...);
static T t;
enum { value = sizeof(is_ptr(t)) == sizeof(char) };
};
struct Foo {
int bar;
};
void testTypeCheck() {
typedef int * IntPtr;
typedef int Foo::* FooMemberPtr;
typedef int (*FuncPtr)();
printf("%d\n",is_pointer<IntPtr>::value); // prints 1
printf("%d\n",is_pointer<FooMemberPtr>::value); // prints 1
printf("%d\n",is_pointer<FuncPtr>::value); // prints 1
}
通過定義4個重載的 is_ptr函數(shù)胜卤,3個是接受不同的指針參數(shù)澈段,另一個則包括了其他的所有參數(shù),
IntPtr 是一個變量指針
FooMemberPtr 是一個成員屬性指針
FuncPtr 是一個函數(shù)指針
接著我們來看下 muduo 庫中的一段代碼:
template<typename T>
struct has_no_destroy {
template<typename C>
static char test(decltype(&C::no_destroy));
template<typename C>
static int32_t test(...);
const static bool value = sizeof(test<T>(0)) == 1;
};
// 其作用就是用來判斷是否有 no_destroy 函數(shù)
struct A {
};
struct B {
void no_destroy(){}
};
struct C {
int no_destroy;
};
struct D : B {
};
void testNoDestroy() {
printf("%d\n",has_no_destroy<A>::value);
printf("%d\n",has_no_destroy<B>::value);
printf("%d\n",has_no_destroy<C>::value);
printf("%d\n",has_no_destroy<D>::value);
}
其作用主要是判斷是否有no_destroy鹦聪,并且在繼承上也成立淘太,但是繼承在不同的gcc版本上不一定成立赌莺,具體可以看:http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
code地址:https://github.com/zhuanxuhit/happy-code/tree/master/src/idioms