替换失败不是static_cast的错误(SFINAE)问题
Substitution failure is not an error (SFINAE) question with static_cast
给定:
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_;
};
如果我尝试:
Hokey h(1);
string s;
h.render(s);
Codepad在静态投射上给了我一个错误:
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&)'
似乎应该说没有Hokey::render
可以匹配。
当然,如果我提供一个有效的过载,一切都会正常工作。但给定下面的代码,您取消对该行的注释,代码板再次阻塞:
string& render(string& s) const {
ostringstream out;
out << i_;
// s = out.str();
return s;
}
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);
}
还应该注意的是,重载解析(因此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");
}
两个模板替换——函数签名——都没有错误,所以两个函数都可以调用,尽管我们知道第一个会失败,第二个不会。因此,这会给您一个不明确的函数调用错误。
您可以使用boost::enable_if
(或C++0x中的std::enable_if
,相当于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);
}
相关文章:
- VS2017 上 SFINAE 的编译错误
- 进行 SFINAE 练习时编译错误
- 尝试编译SFINAE检查中使用的方法体时发生编译错误
- C++ 带有 decltype 的 SFINAE:替换失败成为错误?
- 使用模板时可能是编译器中的 SFINAE 错误?
- 尝试使用具有尾随返回类型的 lambda 进行 SFINAE 时出现硬错误
- 如何对 SFINAE 进行"deep",即当替换导致代码中进一步出现一些编译错误时?
- 尾随返回类型中带有 SFINAE 的 GCC 错误
- 防止编码器错误 - 忘记在"std::enable_if<>::type"中添加"::type" (SFINAE)
- 为什么这个 SFINAE 在 gcc 中给出错误
- 在模板 SFINAE 约束中使用间接寻址级别会导致硬错误
- 使用C ,使用SFINAE测试静态成员的存在,返回错误的值
- 将 SFINAE 上下文中不正确的模板实例化的硬错误转变为软错误
- 在VS2015编译中键入Sfinae,但会产生错误
- VC++ SFINAE 给出错误 C2070:"重载函数":操作数大小非法
- 从MSVC2015更新2移植到GCC 5.3-SFINAE错误
- C++模板sfinae错误
- 模板实例化上的SFINAE错误
- 使用 SFINAE 但不创建编译错误
- 替换失败不是static_cast的错误(SFINAE)问题