在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);
- }