mercredi 25 mai 2016

Expression templates not working for primitive types under clang

I have a CRTP base class as follows:

template<typename Derived, size_t DIMS>
class Base {
public:
    // here is I think where the problem is
    inline const Derived& self() const {return *static_cast<const Derived*>(this);}
};

Then the derived class is defined as

template<typename T, size_t ... Rest>
class Derived: public Base<Derived<T,Rest...>,sizeof...(Rest)> {
public:

    Derived() = default;

    // This constructor binds any arbitrary expression to Derived
    template<typename Expr, size_t DIMS>
    inline Derived(const Base<Expr,DIMS>& src_) {
        const Expr &src = src_.self();
        print(src.rhs);
    }
};

with defining my own operators in mind, I also have the following AddOperator which also inherits from base

template<typename TLhs, typename TRhs, size_t DIMS>
struct AddOperator: public Base<AddOperator<TLhs, TRhs, DIMS>,DIMS> {
    AddOperator(const TLhs& lhs, const TRhs& rhs) : lhs(lhs), rhs(rhs) {
        print(rhs);
    }
    const TLhs &lhs;
    const TRhs &rhs;
};

Then the operator+ overload between a Derived type and a primitive type returns only a proxy/expression of sorts:

template<typename TLhs, typename TRhs, size_t DIM0,
         typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
                                 std::is_arithmetic<TRhs>::value,bool>::type = 0 >
inline AddOperator<TLhs, TRhs, DIM0> 
operator+(const Base<TLhs,DIM0> &lhs, TRhs rhs) {
  return AddOperator<TLhs, TRhs, DIM0>(lhs.self(), rhs);
}

However, when I call this under clang I get garbage values for rhs of AddOperator. Here is an example:

int main() {

    Derived<double,2,2> g;
    Derived<double,2,2> x = g+28;

    return 0;
}

The other overloads when both lhs and rhs in AddOperator are of type Derived do not have this problem.

This problem happens only under clang. gcc compiled code seems to run fine. Does anyone know where the problem is?

Full Demo Here

Aucun commentaire:

Enregistrer un commentaire