编译时检查输出(<<)和关系(<、>等)是否可用
Compile-time check whether output (<<) and relational (<, >, etc.) are available
我目前正在使用is_call_possible
第三方代码
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
你能给我指一下方便的第三方代码(或你自己的代码)吗?
如果更容易的话,底层解决方案("第三方代码")可以在C++11中实现,但我想我不会注意到我自己的代码中的差异(作为第三方码的用户)。
假设C++11是一个选项,decltype
编译时构造可以与SFINAE一起使用,基本上对类型进行"概念检查"(尽管C++11标准中缺乏真正的概念检查),看看它们是否支持操作。
(未经测试,因为我目前缺少C++11编译器[诅咒你的Windows~!],但我相信如果我的错误存在,会有人发现的)。
Ex。
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)
提升型特征可以做到这一点。
注意:模板代码仍然存在问题(无论您使用哪种方法来检测它)。例如,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
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中