在 C++11 之前的版本中,当使用特定参数调用时,如何确定给定函数是否返回引用?
例如,如果代码如下所示:
template<class F>
bool returns_reference(F f) { return is_reference(f(5)); }
那我应该如何实现is_reference
呢?
请注意 f
也可能是一个仿函数,它的 operator()
可能有多个重载——我只关心通过我的参数实际调用的重载在这里。
最佳答案
这是一个基于 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, yields_lvalue_1<foo, 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), long>::result);
print(false, yields_lvalue_1<foo(&)(int), short>::result);
}
关于c++ - C++03中如何判断函数是否返回引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20024092/