我正在处理几种表达式模板,我需要知道这些表达式的计算结果(例如double
)。其中一些表达模板来自3rd party库。
我正在定义特征:
template <typename X1>
struct EvaluatedType
由于我不能使用本身就是模板的参数来专门化模板(例如EvaluatedType<MyExpression<T>>
),所以我不专门化它,而是依靠可以重载的函数evaluate1
(包括一些模板重载) ):
template <typename X1>
struct EvaluatedType
{
using Type = decltype(evaluate1(std::declval<X1>()));
};
evaluate1
不能是成员函数,因为它必须接受double
之类的类型并支持第三方表达式模板类型。
我遇到的第一个问题是(MWE):
#include <type_traits>
#include <string>
std::string evaluate1(std::string a)
{return a;}
double evaluate1(double a)
{return a;}
template <typename X1>
struct EvaluatedType
{
using Type = decltype(evaluate1(std::declval<X1>()));
};
int main()
{
EvaluatedType<double>::Type a;
a = 0.0;
(void) a+5.0;
}
此代码无法编译为:
error: invalid operands of types ‘void’ and ‘double’ to binary ‘operator+’
(void) a+5.0;
a
的类型为void
,但我不明白为什么,因为evaluate1(double)
的返回类型为double
。
我的另一个问题是,如果将evaluate1(double)
的定义移到EvaluatedType
的定义之后,它将无法创建EvaluatedType<double>::Type
(它只能看到之前定义的字符串版本) 。这是有问题的,因为我希望其他开发人员能够为其表达式模板添加evaluate1
的新版本,并能够在其他特征中使用EvaluatedType<Expr>
来了解表达式将求值的类型。 / p>
有没有一种方法可以定义这种类型:
template <typename X1>
struct EvaluatedType;
以EvaluatedType<X1>::Type
为参数类型为evaluate1
的调用X1
的返回类型。
谢谢。
注意:我必须支持主要符合c ++ 11的gcc 4.8.5。
解决方案
从评论和答案来看,问题是:
由于我不能将ADL与double一起使用,因此必须在定义ResultType之前定义double的评估方法。对于其他评估方法,我必须确保它们在与参数相同的命名空间中定义。
template <typename X> typename std::enable_if<std::is_arithmetic<X>::value,double>::type evaluate(const X & x)
{
return x;
}
template <typename X>
struct EvaluatedType
{
using Type = decltype(evaluate(std::declval<X>()));
};
对于我们用于自动区分的表达式模板库,这些表达式的表达式从名称空间autodif中其自身类型(CRTP)的ScalarBase继承而来,其评估为xdouble(也继承了ScalarBase),其中包含double(值)+稀疏梯度向量。 :
namespace autodif
{
template < typename X > xdouble evaluate(const ScalarBase<X> & x)
{
return x; // implicitly convert with xdouble template constructor
}
} // autodif
答案 0 :(得分:2)
(void) a+5.0;
这是((void)a)+5.0;
你想要
(void)(a+5.0);