在C 11之前的版本中,当使用特定参数调用时,如何确定给定函数是否返回引用?
例如,如果代码如下所示:
template<class F> bool returns_reference(F f) { return is_reference(f(5)); }
那我该如何实现is_reference?
解决方法
这是一个基于SFINAE的解决方案,用于检查函数调用表达式是否产生左值:
#include <boost/type_traits.hpp> #include <boost/utility.hpp> #include <cstddef> // Func: function (object/pointer/reference) type // Arg0: type of the first argument to use (for overload resolution) template<class Func,class Arg0> struct yields_lvalue_1 // with one argument { typedef char yes[1]; typedef char no[2]; // decay possible function types typedef typename boost::decay<Func>::type F_decayed; // a type whose constructor can take any lvalue expression struct Any { template<class T> Any(T&); }; // SFINAE-test: if `Any(....)` is well-formed,this overload of `test` is // viable template<class T> static yes& test(boost::integral_constant<std::size_t,sizeof(Any( boost::declval<T>()(boost::declval<Arg0>()) ))>*); // fall-back template<class T> static no& test(...); // perform test static bool const result = sizeof(test<F_decayed>(0)) == sizeof(yes); };
一些示例性功能对象:
struct foo { bool& operator()(int); bool operator()(double); }; struct bar { template<class T> double operator()(T); };
用法示例:
#include <iostream> #include <iomanip> void print(bool expect,bool result) { std::cout << "expect: "<<std::setw(5)<<expect<<" -- result: "<<result<<"\n"; } int main() { std::cout << std::boolalpha; print(true,yields_lvalue_1<foo,int> ::result); print(false,double>::result); print(false,yields_lvalue_1<bar,int> ::result); print(true,yields_lvalue_1<foo&(*)(long),int>::result); print(false,yields_lvalue_1<void(*)(int),short>::result); print(true,yields_lvalue_1<bool&(short),long>::result); print(false,yields_lvalue_1<void(float),int>::result); print(true,yields_lvalue_1<char&(&)(bool),yields_lvalue_1<foo(&)(int),short>::result); }