简体   繁体   English

表达式模板:错误C2784'无法推断出模板参数'

[英]Expression Templates: error C2784 'could not deduce template argument'

I am working on a vector class that uses expression templates. 我正在使用表达式模板的矢量类。 I have the following (reduced) code. 我有以下(简化)代码。 In "Vector.h": 在“Vector.h”中:

#include <cmath>
#include <iostream>
#include <limits>
#include <type_traits>

#define NULLVAL(a) (*((a*) 0))

namespace VectorExpression {
    template <typename E, typename R> class Expression;
    template <typename E, typename R, typename S, typename Op> class ScalarBinary;
    template <tyepname E1, typename R1, typename E2, typename R2, typename Op> class VectorBinary;
    template <typename T1, typename T2> struct Div;
    template <typename T1, typename T2> struct Div2;
    template <typename T> class Vector;
};

template <typename E, typename R, typename S>
typename std::enable_if<std::is_arithmetic<S>::value, VectorExpression::ScalarBinary<E, R, S, VectorExpression::Div<R, S>>>::type
operator/(const VectorExpression::Expression<E, R> &expr, S a)  // LINE #136
{
    return ( VectorExpression::ScalarBinary<E, R, S, VectorExpression::Div<R, S>>(expr, a) );
}

template <typename E, typename R, typename S>
typename std::enable_if<std::is_arithmetic<S>::value, VectorExpression::ScalarBinary<E, R, S, VectorExpression::Div2<R, S>>>::type
operator/(S a, const VectorExpression::Expression<E, R> &expr)  // LINE #143
{
    return ( VectorExpression::ScalarBinary<E, R, S, VectorExpression::Div2<R, S>>(expr, a) );
}

template <typename E1, typename R1, typename E2, typename R2>
auto operator/(const VectorExpression::Expression<E1, R1> &expr1, const VectorExpression::Expression<E2, R2> &expr2) -> VectorExpression::VectorBinary<E1, R1, E2, R2, VectorExpression::Div<R1, R2>>  // LINE #174
{
    return ( VectorExpression::VectorBinary<E1, R1, E2, R2, VectorExpression::Div<R1,R2>>(expr1, expr2) );
}

// length #1
template <typename E, typename R>
double length(const VectorExpression::Expression<E, R> &expr)
{
    return ( sqrt( pow(expr.x(), 2) + pow(expr.y(), 2) + pow(expr.z(), 2) );
}

// length #2
template <typename T>
double length(const VectorExpression::Expression<Vector<T>, T> &expr) // length #2
{
    return ( sqrt( expr.x() * expr.x() + expr.y() * expr.y() + expr.z() * expr.z() );
}

// normalize #1
template <typename E, typename R>
auto normalize(const VectorExpression::Expression<E, R> &expr) -> decltype( NULLVAL(Vector<double>) / NULLVAL(double) )
{
    Vector<double> v(expr);
    return ( v / v.length() );
}

// normalize #2
template <typename T>
auto normalize(const VectorExpression::Expression<Vector<T>, T> &expr) -> decltype( NULLVAL(Vector<double>) / NULLVAL(double) )
{
    return ( static_cast<Vector<double>>(expr) / expr.length() );
}

namespace VectorExpression {
    template <typename E, typename R>
    class Expression {
    protected:
        Expression() { }

    public:
        typedef R value_type;

        value_type x() const
        {
            return ( static_cast<const E&>(*this).x() );
        }
        value_type y() const
        {
            return ( static_cast<const E&>(*this).y() );
        }
        value_type z() const
        {
            return ( static_cast<const E&>(*this).z() );
        }


        double length() const
        {
            return ( ::length(static_cast<const E&>(*this)) );
        }
        auto normalize() -> decltype( NULLVAL(Vector<double>) / NULLVAL(double) )  // LINE #323
        {
            return ( ::normalize(static_cast<const E&>(*this)) );
        }
    };

    template <typename E, typename R, typename S, typename Op>
    class ScalarBinary : public Expression<ScalarBinary<E, R, S, Op>, typename Op::value_type> {
    private:
        const E& v;
        S a;

    public:
        ScalarBinary(const Expression<E, R> &expr, S scalar) : v(expr), a(scalar) { }

        value_type x() const
        {
            return ( Op::apply( v.x(), a ) );
        }
        value_type y() const
        {
            return ( Op::apply( v.y(), a ) );
        }
        value_type z() const
        {
            return ( Op::apply( v.z(), a ) );
        }
    };

    template <typename E1, typename R1, typename E2, typename R2, typename Op>
    class VectorBinary : public Expression<VectorBinary<E1, R1, E2, R2, Op>, typename Op::value_type> {
    private:
        const E1 &v1;
        const E2 &v2;

    public:
        VectorBinary(const Expression<E1, R1> &expr1, const Expression<E2, R2> &expr2) : v1(expr1), v2(expr2) { }

        value_type x() const
        {
            return ( Op::apply( v1.x(), v2.x() ) );
        }
        value_type y() const
        {
            return ( Op::apply( v1.y(), v2.y() ) );
        }
        value_type z() const
        {
            return ( Op::apply( v1.z(), v2.z() ) );
        }
    };

    template <typename T1, typename T2>
    struct Div {
        typedef decltype( NULLVAL(T1) / NULLVAL(T2) ) value_type;
        static value_type apply( T1 x1, T2 x2 ) { return ( x1 / x2 ); }
    };

    template <typename T1, typename T2>
    struct Div2 {
        typedef decltype( NULLVAL(T2) / NULLVAL(T1) ) value_type;
        static value_type apply( T1 x1, T2 x2 ) { return ( x2 / x1 ); }
    };

    template <typename T>
    class Vector : public Expression<Vector<T>, T> {  // LINE #578
    private:
        T _x, _y, _z;

    public:
        template <typename U1, typename U2, typename U3>
        Vector(U1 X, U2 Y, U3 Z) : _x(static_cast<T>(X)), _y(static_cast<T>(Y)), _z(static_cast<T>(Z)) { }


        template <typename E, typename R>
        Vector(const Expression<E, R> &expr) : _x(static_cast<T>(expr.x())), _y(static_cast<T>(expr.y())), _z(static_cast<T>(expr.z())) { }

        value_type x() const
        {
            return ( this->_x );
        }
        value_type y() const
        {
            return ( this->_y );
        }
        value_type z() const
        {
            return ( this->_z );
        }
    };
};

Then, in "main.cpp": 然后,在“main.cpp”中:

#include "Vector.h"

int main(int argc, char *argv[])
{
    Vector<double> a(0.5, 1.5, 2.5), b;  // LINE #12
    double c;

    c = length(a);  // calls length #1
    c = length(a/2.0);  // calls length #2
    a.length();  // calls length #1
    (a/2).length();  // calls length #2
    b = normalize(a);  // calls normalize #1
    b = normalize(a/2.0);  // calls normalize #2

    return ( 0 );
}

Now, if I comment out the member normalize in class Expression , the code compiles, and everything works as I expect, including which versions of length and normalize get called. 现在,如果我在类Expression注释掉该成员normalize ,代码将编译,并且一切都按预期工作,包括调用lengthnormalize哪个版本。 However, if I leave the member normalize uncommented, I get the following compiler error: 但是,如果我让成员normalize uncommented,我得到以下编译器错误:

vector.h(323): error C2784: 'VectorExpression::VectorBinary<E1,R1,E2,R2,VectorExpression::Div<R1,R2>> operator /(const VectorExpression::_Expression<E,R> &,const VectorExpression::_Expression<E2,R2> &)' : could not deduce template argument for 'const VectorExpression::_Expression<E,R> &' from 'VectorExpression::Vector<T>'
with
[
    T=double
]
vector.h(174) : see declaration of 'operator /'
vector.h(384) : see reference to class template instantiation 'VectorExpression::_Expression<E,R>' being compiled
with
[
    E=VectorExpression::Vector<double>,
    R=double
]
vector.h(578) : see reference to class template instantiation 'VectorExpression::Expression<E,R>' being compiled
with
[
    E=VectorExpression::Vector<double>,
    R=double
]
main.cpp(12) : see reference to class template instantiation 'VectorExpression::Vector<T>' being compiled
with
[
    T=double
]
vector.h(323): error C2784: 'std::enable_if<std::is_arithmetic<S>::value,VectorExpression::ScalarBinary<E,R,S,VectorExpression::Div2<R,S>>>::type operator /(S,const VectorExpression::_Expression<E,R> &)' : could not deduce template argument for 'const VectorExpression::_Expression<E,R> &' from 'double'
vector.h(143) : see declaration of 'operator /'
vector.h(323): error C2784: 'std::enable_if<std::is_arithmetic<S>::value,VectorExpression::ScalarBinary<E,R,S,VectorExpression::Div<R,S>>>::type operator /(const VectorExpression::_Expression<E,R> &,S)' : could not deduce template argument for 'const VectorExpression::_Expression<E,R> &' from 'VectorExpression::Vector<T>'
with
[
    T=double
]
vector.h(136) : see declaration of 'operator /'
vector.h(323): error C2676: binary '/' : 'VectorExpression::Vector<T>' does not define this operator or a conversion to a type acceptable to the predefined operator
with
[
    T=double
]

I would like to be able to call normalize as either a standalone function acting on a Vector or Expression or as an inherited member of Expression similar to the way it is done with length , which compiles and works correctly. 我想能够正常化作为来电或者作用于一个独立的功能VectorExpression或作为一个继承的成员Expression类似于它与完成的方式length ,它编译并正常工作。 The standalone versions of normalize also work correctly. normalize的独立版本也可以正常工作。 What is wrong with my definition of normalize as a class member? 我将normalize定义为类成员有什么问题?

Thanks! 谢谢!

It compiles and works correctly if I change 如果我改变,它编译并正常工作

auto normalize() -> decltype( NULLVAL(Vector<double>) / NULLVAL(double) )

in the class Expression to 在类Expression

auto normalize() -> decltype( (*((Expression<Vector<double>,double>*) 0)) / NULLVAL(double) )

However, I do not understand why this is necessary. 但是,我不明白为什么这是必要的。 The standalone declarations of normalize use the former style of decltype and work correctly, and Vector<double> inherits from Expression<Vector<double>,double> , so I don't understand why I must make this change. normalize的独立声明使用以前的decltype样式并正常工作, Vector<double>继承自Expression<Vector<double>,double> ,所以我不明白为什么我必须进行此更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM