3

我目前正在使用第is_call_possible3 方代码

https://github.com/jaredhoberock/is_call_possible

在编译时确定成员是否可用。这个例子很好用:

#include <string>
#include "is_call_possible.h"

DEFINE_IS_CALL_POSSIBLE(is_call_possible, operator())
DEFINE_IS_CALL_POSSIBLE(test_available, test)

struct Foo {
  void operator()(double) {}
  double test(std::string) { return 0; }
};

int main(int argc, const char * argv[]) {
  static_assert(is_call_possible<Foo, void(double)>::value,"err"); //success
  static_assert(test_available<Foo, double(std::string)>::value,"err"); //success
  return 0;
}

但这不适用于普通的非成员,所以我不能对输出和关系运算符做同样的事情:

DEFINE_IS_CALL_POSSIBLE(output_available, operator<<) //error
DEFINE_IS_CALL_POSSIBLE(less_available, operator<) //error
DEFINE_IS_CALL_POSSIBLE(greater_available, operator>) //error

你能指出我方便的第 3 方代码(或你自己的代码)来适应这个吗?

如果更容易的话,可以在 C++11 中实现底层解决方案(“第 3 方代码”),但我想我不会注意到我自己的代码(作为第 3 方代码的用户)的差异。

4

2 回答 2

1

假设 C++11 是一个选项,decltype编译时构造可以与 SFINAE 结合使用,基本上对类型进行“概念检查”(尽管 C++11 标准中缺乏真正的概念检查),看看是否他们支持运营。

(未经测试,因为我目前缺少 C++11 编译器 [诅咒你的 Windows~!],但我敢肯定,如果它们存在,有人会发现我的错误)。

前任。

template<typename T> struct voidify{typedef void type;};
template<typename T, typename U, typename enable=void>
struct has_operator_less {
  enum{value=false};
};
template<typename T, typename U>
struct has_operator_less<T, U, typename voidify<decltype(
  std::declval<T>() < std::declval<U>() // <-- this is the 'concept' check
)>::type> {
  enum{value=true};
};

并且您可以使用它来启用/禁用std::enable_if任何依赖于operator<这两种类型存在或不存在的函数的构造:

template<typename T, typename U>
typename std::enable_if<
  has_operator_less<T, U>::value, I_am_the_result_type_of_the_function
>::type
I_depend_on_the_existence_of_the_less_than_operator(const T& a, const U& b) {...}

如果您想要为缺少 的类型提供该函数的替代实现operator<,您只需使用否定启用:

template<typename T, typename U>
typename std::enable_if<
  !has_operator_less<T, U>::value, I_am_the_result_type_of_the_function
  // ^ note the negation
>::type
I_depend_on_the_existence_of_the_less_than_operator(const T& a, const U& b) {...}

因此,现在您已经在编译时确定了具有和不具有这些运算符的类型的实现,并且可以为任何其他运算符或函数名称或您想要的任何内容重复此解决方案。只需将您要检查的概念放入decltype.

这些都不需要在构建之前进行单独的配置步骤。

(同样,未经测试的代码 -.-' 但很确定是正确的;你们其他人都知道编辑按钮在哪里 :-P )

于 2013-06-22T01:25:07.870 回答
0

Boost Type Traits会做到这一点。

注意:模板代码仍然存在问题(无论您使用哪种方法来检测它)。例如,vector<T>::operator<假设T有一个operator<,所以你得到以下内容:

struct Silly {};

std::cout << boost::has_less<Silly>::value << std::endl;  // 0
std::cout << boost::has_less<std::vector<Silly>>::value << std::endl;  // 1
于 2013-06-24T14:54:31.750 回答