Menu Home

CPP: SFINAE

SFINAE(Substitution failure is not an error)是C++范型编程中的概念。
对SFINAE简单的理解是,当编译器发现最佳模版匹配失败的时候,不报错,而是继续寻找第二匹配。
在Java中我们可以通过反射机制来判断某个类中是否包含了某个方法,但是C++没有反射,但可以通过SFINAE来达到同样的目的。
WIKI中提供了一个非常简洁的代码片段来演示SFINAE:

struct Test {
    typedef int foo;
};
 
template <typename T> 
void f(typename T::foo) {} // Definition #1
 
template <typename T> 
void f(T) {}                // Definition #2
 
int main() {
    f<Test>(10); // Call #1.
    f<int>(10);  // Call #2. Without error (even though there is no int::foo) thanks to SFINAE.
}

我们看到第2个调用:f(10)中的模板参数为int,编译器为它匹配了Definition #2。

下面的代码演示了如何在C++中判断一个函数是否属于某个类:

#include <iostream>
 
template <typename T>
struct has_typedef_foobar {
    // Types "yes" and "no" are guaranteed to have different sizes,
    // specifically sizeof(yes) == 1 and sizeof(no) == 2.
    typedef char yes[1];
    typedef char no[2];
 
    template <typename C>
    static yes& test(typename C::foobar*);
 
    template <typename>
    static no& test(...);
 
    // If the "sizeof" of the result of calling test<T>(0) would be equal to sizeof(yes),
    // the first overload worked and T has a nested type named foobar.
    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
 
struct foo {    
    typedef float foobar;
};
 
int main() {
    std::cout << std::boolalpha;
    std::cout << has_typedef_foobar<int>::value << std::endl;
    std::cout << has_typedef_foobar<foo>::value << std::endl;
}

ref: http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error

Leave a Reply

Your email address will not be published.