C 11:过载分辨率和SFINAE

C 11:过载分辨率和SFINAE,第1张

概述我正在学习SFINAE,这是我第一次尝试打印“YES”,只能用于std :: ostream(请忘记std :: operator<(std :: ostream& T))输出的类型...): template <typename T>void f(const T &) { std::cout << "NO" << std::endl; }template <typename T, int 我正在学习SFINAE,这是我第一次尝试打印“YES”,只能用于std :: ostream(请忘记std :: operator<(std :: ostream& T))输出的类型...):
template <typename T>voID f(const T &) { std::cout << "NO" << std::endl; }template <typename T,int SFINAE = sizeof(static_cast<std::ostream &(std::ostream::*)(T)>(    &std::ostream::operator<<))>voID f(const T &) { std::cout << "YES" << std::endl; }

虽然它们似乎与f(std :: vector< int>())(产生“否”)一起工作,但编译器抱怨f(0)是不明确的:http://ideone.com/VljXFh

prog.cpp:16:5: error: call of overloaded 'f(int)' is ambiguous  f(0);     ^prog.cpp:6:6: note: candIDate: voID f(const T&) [with T = int] voID f(const T &) { std::cout << "NO" << std::endl; }      ^prog.cpp:10:6: note: candIDate: voID f(const T&) [with T = int; int SFINAE = 8] voID f(const T &) { std::cout << "YES" << std::endl; }      ^

如何修复我的代码? “YES”版本是否比完全通用的“NO”版本更具体?

澄清

f(0),f(0.)和f(true)全部失败,出现相同的“模糊”错误.我正在寻找一种适用于std::ostream::operator<<接受的所有类型的解决方案.理想情况下,它不应该依赖于定义一个帮助类型“命令”命名空间.

解决方法 NO版本对于int仍然有效,并且没有适用的部分顺序在两个重载之间进行选择,所以调用是不明确的.

消除歧义的一个简单方法是在函数中添加一个额外的变量参数:

template <typename T>voID f(const T &,char) { std::cout << "NO" << std::endl; }//                ^^^^template <typename T,int SFINAE = sizeof(static_cast<std::ostream &(std::ostream::*)(T)>(    &std::ostream::operator<<))>voID f(const T &,int) { std::cout << "YES" << std::endl; }//                ^^^

现在当你调用该函数时,只需传递一个0(或者写一个帮助函数来为你做).如果它是有效的,则SFINAE保护函数将是首选的,因为int是比char更好的匹配0.有关更清楚的表示此消歧的方法,请参见this article.

或者,您可以编写一个特征来检查 *** 作符是否对于给定类型有效,然后使用std :: enable_if< check< T>>和std :: enable_if<!check< T>>以避免歧义.

顺便提一句,你可以使用这种SFINAE的decltype和tail返回类型,我觉得看起来有点干净:

template <typename T>voID f(const T &,char) { std::cout << "NO" << std::endl; }template <typename T>auto f(const T &t,int) -> decltype(std::declval<std::ostream&>() << t,voID()){ std::cout << "YES" << std::endl; }

当我们得到C概念,你将能够做这样的事情(这在启用概念的GCC中有效):

template <typename T>concept bool Outputtable = requires (T t,std::ostream o) { o << t; };template <typename T>voID f(const T &) { std::cout << "NO" << std::endl; }template <Outputtable T>voID f(const T &) { std::cout << "YES" << std::endl; }
总结

以上是内存溢出为你收集整理的C 11:过载分辨率和SFINAE全部内容,希望文章能够帮你解决C 11:过载分辨率和SFINAE所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/1249593.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存