vendredi 30 août 2019

Templated return type specialisation for expression templates

I am dealing with several kinds of expressions template and I need to know what those expressions evaluate to (eg double). Some of these expression templates come from 3rd party library.

I am defining the traits:

template <typename X1>
struct EvaluatedType

Since I cannot specialize a template with arguments that are themselves a template ( eg EvaluatedType<MyExpression<T>> ), I do not specialize it but rather rely on a function evaluate1 that I can overload (including some templated overloads):

template <typename X1>
struct EvaluatedType
{
    using Type = decltype(evaluate1(std::declval<X1>()));
};

evaluate1 cannot be a member function because it has to accept types such as double and support 3rd party expression template types.

The first problem I am encountering is (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;
}


This code fails to compile with:

error: invalid operands of types ‘void’ and ‘double’ to binary ‘operator+’
 (void) a+5.0;

a is of type void but I do not understand why because the return type of evaluate1(double) is double.

My other problem is that if I move the definition of evaluate1(double) after the definition of EvaluatedType, it fails to create EvaluatedType<double>::Type (it only sees the string version which is defined before). This is problematic because I would like other developers to be able to add new version of evaluate1 for their expression templates and be able to use EvaluatedType in other traits to know the type an expression will evaluate to.

Is there a way to define such a type:

template <typename X1>
struct EvaluatedType;

in a way that EvaluatedType<X1>::Type will be the return type of calling evaluate1 with argument of type X1.

Thank you.

Note: I have to support gcc 4.8.5 which is mostly c++11 compliant.

Aucun commentaire:

Enregistrer un commentaire