我尝试编写表达式模板。
template<typename Tag>
struct Expr{
tuple<Tag> value;
};
struct logic_and{};
template<typename T>
struct isExpr{enum{value=0};};
template<typename Tag>
struct isExpr<Expr<Tag>>{enum{value=1};};
template<typename L,typename R,typename=std::enable_if<isExpr<L>::value||isExpr<R>::value> >
Expr<logic_and> operator&&(const L&,const R&)
{
return {};
}
但mingw gcc 4.8.1错误:
...include\c++\ext\string_conversions.h||In instantiation of '_Ret __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = int; _CharT = char; _Base = {int}; std::size_t = long long unsigned int]':|
...include\c++\bits\basic_string.h|2825|required from here|
...include\c++\ext\string_conversions.h|67|error: no match for 'operator||' (operand types are 'bool' and 'Expr<logic_and>')|
...include\c++\ext\string_conversions.h|67|note: candidate is:|
...include\c++\ext\string_conversions.h|67|note: operator||(bool, bool) <built-in>|
...include\c++\ext\string_conversions.h|67|note: no known conversion for argument 2 from 'Expr<logic_and>' to 'bool'|
...include\c++\ext\string_conversions.h||In instantiation of '_Ret __gnu_cxx::__stoa(_TRet (*)(const _CharT*, _CharT**, _Base ...), const char*, const _CharT*, std::size_t*, _Base ...) [with _TRet = long int; _Ret = long int; _CharT = char; _Base = {int}; std::size_t = long long unsigned int]':|
看起来找到一个bool结果......如果我替换为
template<typename L,typename R,typename=std::enable_if<isExpr<L>::value||isExpr<R>::value> >
Expr<logic_and> operator||(const L&,const R&)
{
return {};
}
或替换为
template<typename L,typename R,typename=std::enable_if<isExpr<L>::value||isExpr<R>::value> >
bool operator&&(const L&,const R&)
{
return {};
}
全部通过!是gcc bug?我该如何解决?
编辑抱歉我误导了enable_if ....现在我重现了这个错误:
#include <type_traits>
#include <memory>
namespace TestFoo{
struct Tag {};
struct shift_left:Tag {};
struct shift_right:Tag {};
struct multiplies:Tag {};
struct divides:Tag {};
struct modulus:Tag {};
struct plus:Tag {};
struct minus:Tag {};
struct less:Tag {};
struct greater:Tag {};
struct less_equal:Tag {};
struct greater_equal:Tag {};
struct equal_to:Tag {};
struct not_equal_to:Tag {};
struct logical_or:Tag {};
struct logical_and:Tag {};
struct bitwise_and:Tag {};
struct bitwise_or:Tag {};
struct bitwise_xor:Tag {};
struct shift_left_assign:Tag {};
struct shift_right_assign:Tag {};
struct multiplies_assign:Tag {};
struct divides_assign:Tag {};
struct modulus_assign:Tag {};
struct plus_assign:Tag {};
struct minus_assign:Tag {};
struct bitwise_and_assign:Tag {};
struct bitwise_or_assign:Tag {};
struct bitwise_xor_assign:Tag {};
template<typename Tag,typename...ARGS>
class Expr
{
public:
template<typename...SRC>
Expr(SRC const&...src){
}
private:
};
template<typename T>
struct is_expr{
enum{value=0};
};
template<typename Tag,typename...ARGS>
struct is_expr<Expr<Tag,ARGS...>>{
enum{value=sizeof...(ARGS)};
};
#define BinaryOp(op,name) \
template<typename L,typename R,typename=typename std::enable_if<is_expr<L>::value||is_expr<R>::value>::type>\
Expr<name,L,R> operator op(const L&l,const R&r)\
{\
return {std::forward<const L&>(l),std::forward<const R&>(r)};\
}
BinaryOp(<<,shift_left)
BinaryOp(>>,shift_right)
BinaryOp(*,multiplies)
BinaryOp(%,modulus)
BinaryOp(+,plus)
BinaryOp(-,minus)
BinaryOp(<,less)
BinaryOp(>,greater)
BinaryOp(<=,less_equal)
BinaryOp(>=,greater_equal)
BinaryOp(==,equal_to)
BinaryOp(!=,not_equal_to)
BinaryOp(||,logical_or)
BinaryOp(&&,logical_and)
}
.cpp:
#include "test.h"
using namespace TestFoo;//using namespace Appear bug
void test(){
}
如果我删除BinaryOp(&&,logical_and)
,或者不在.cpp中使用命名空间,或者删除所有std :: forward,则成功编译。否则吃内存直到失败。
答案 0 :(得分:1)
std::enable_if<isExpr<L>::value||isExpr<R>::value>
以上是有效类型,无论<>
enable_if
内的内容是什么。
typename std::enable_if<isExpr<L>::value||isExpr<R>::value>::type
当且仅当bool
<>
中的enable_if
表达式为true
时,才是有效类型。
简而言之,你没有成功地做SFINAE,所以预期会出现奇怪的行为。特别是,您的重载运算符声称处理const bool&||const bool&
和许多其他类型的业务,它没有业务搞乱。
我无法解码错误,但首先修复代码。
答案 1 :(得分:0)
使用
template<typename L, typename R, typename = typename std::enable_if<is_expr<L>::value && is_expr<R>::value>::type>
Expr<name, L, R> operator op(const L&l, const R&r);
你进入(编译器)递归operator ||
:此运算符可以使用枚举 {{1来评估(未命名)枚举 is_expr<L>::value
需要考虑is_expr<R>::value
...
解决方案是将is_expr<decltype(is_expr<L>::value)>::value
替换为enum
。 (见https://ideone.com/pqhmv1)