据我了解,您希望进行通用测试以查看类是否具有某个成员函数。这可以在 C++ 中使用SFINAE 来完成。在 C++11 中它非常简单,因为您可以使用 decltype:
template <typename T>
struct has_size {
private:
template <typename U>
static decltype(std::declval<U>().size(), void(), std::true_type()) test(int);
template <typename>
static std::false_type test(...);
public:
typedef decltype(test<T>(0)) type;
enum { value = type::value };
};
如果你使用C++03,由于缺少decltype,会有点困难,所以你必须滥用sizeof:
template <typename T>
struct has_size {
private:
struct yes { int x; };
struct no {yes x[4]; };
template <typename U>
static typename boost::enable_if_c<sizeof(static_cast<U*>(0)->size(), void(), int()) == sizeof(int), yes>::type test(int);
template <typename>
static no test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(yes) };
};
当然这使用了Boost.Enable_If,这可能是一个不需要的(和不必要的)依赖。但是自己写enable_if 非常简单:
template<bool Cond, typename T> enable_if;
template<typename T> enable_if<true, T> { typedef T type; };
在这两种情况下,方法签名 test<U>(int) 仅在 U 具有 size 方法时可见,否则评估 decltype 或 sizeof(取决于您使用的版本)将失败,然后将删除该方法(由于SFINAE。冗长的表达式std::declval<U>().size(), void(), std::true_type()是对C++逗号运算符的滥用,它将返回逗号分隔列表中的最后一个表达式,因此确保类型为对于 C++11 变体,称为 std::true_type(对于 C++03 变体,sizeof 评估 int)。中间的 void() 只是为了确保没有奇怪的重载干扰评估的逗号运算符。
当然,如果T 有一个size 方法可以在没有参数的情况下调用,那么这将返回true,但不保证返回值。我假设您可能只想检测那些不返回 void 的方法。这可以通过对test(int) 方法的轻微修改轻松完成:
// C++11
template <typename U>
static typename std::enable_if<!is_void<decltype(std::declval<U>().size())>::value, std::true_type>::type test(int);
//C++03
template <typename U>
static typename std::enable_if<boost::enable_if_c<sizeof(static_cast<U*>(0)->size()) != sizeof(void()), yes>::type test(int);