鉴于:
class Hokey
{
public:
explicit C(int i): i_(i) { }
template<typename T>
T& render(T& t) { t = static_cast<T>(i_); return t; }
private:
unsigned i_;
};
Run Code Online (Sandbox Code Playgroud)
如果我尝试:
Hokey h(1);
string s;
h.render(s);
Run Code Online (Sandbox Code Playgroud)
t.cpp: In member function 'T& Hokey::render(T&) [with T = std::string]':
t.cpp:21: instantiated from here
Line 11: error: no matching function for call to 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(unsigned int&)'
Run Code Online (Sandbox Code Playgroud)
似乎应该说没有Hokey::render可比的.
当然,如果我提供有效的过载,一切正常.但是根据下面的代码,你再次取消注释行,键盘扼流圈:
string& render(string& s) const {
ostringstream out;
out << i_;
// s = out.str();
return s;
}
Run Code Online (Sandbox Code Playgroud)
不是SFINAE说 - 在第一种情况下 - 渲染中的问题不应该是错误,而是缺少有效的渲染应该是错误吗?
在重载解析期间,这不是错误.换句话说,它会给你一个错误,直到确定这个调用肯定不会起作用.在那之后,这是一个错误.
struct example
{
template <typename T>
static void pass_test(typename T::inner_type); // A
template <typename T>
static void pass_test(T); // B
template <typename T>
static void fail_test(typename T::inner_type); // C
};
int main()
{
// enumerates all the possible functions to call: A and B
// tries A, fails with error; error withheld to try others
// tries B, works without error; previous error ignored
example::pass_test(5);
// enumerates all the possible functions to call: C
// tries C, fails with error; error withheld to try others
// no other functions to try, call failed: emit error
example::fail_test(5);
}
Run Code Online (Sandbox Code Playgroud)
还应注意,重载决策(以及因此SFINAE)仅查看函数签名,而不是定义.所以这总是会失败:
struct example_two
{
template <typename T>
static int fail_test(T x)
{
return static_cast<int>(x);
}
template <typename T>
static int fail_test(T x)
{
return boost::lexical_cast<int>(x);
}
};
int main()
{
example_two::fail_test("string");
}
Run Code Online (Sandbox Code Playgroud)
模板替换没有错误 - 对于函数签名 - 所以两个函数都可以调用,即使我们知道第一个函数会失败而第二个函数也不会.所以这会给你一个模糊的函数调用错误.
您可以使用boost::enable_if(或std::enable_if在C++ 0x中,等效于boost::enable_if_c)显式启用或禁用函数.例如,您可以使用以下方法修复上一个示例:
struct example_two_fixed
{
template <typename T>
static boost::enable_if<boost::is_convertible<T, int>, int>
pass_test(T x) // AA
{
return static_cast<int>(x);
}
template <typename T>
static boost::disable_if<boost::is_convertible<T, int>, int>
pass_test(T x) // BB
{
return boost::lexical_cast<float>(x);
}
};
struct empty {} no_conversion;
int main()
{
// okay, BB fails with SFINAE error because of disable_if, does AA
example_two::pass_test(5);
// okay, AA fails with SFINAE error because of enable_if, does BB
example_two::pass_test("string");
// error, AA fails with SFINAE, does BB, fails because cannot lexical_cast
example_two::pass_test(no_conversion);
}
Run Code Online (Sandbox Code Playgroud)