簡體   English   中英

表達式模板:錯誤C2784'無法推斷出模板參數'

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

我正在使用表達式模板的矢量類。 我有以下(簡化)代碼。 在“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 );
        }
    };
};

然后,在“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 );
}

現在,如果我在類Expression注釋掉該成員normalize ,代碼將編譯,並且一切都按預期工作,包括調用lengthnormalize哪個版本。 但是,如果我讓成員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
]

我想能夠正常化作為來電或者作用於一個獨立的功能VectorExpression或作為一個繼承的成員Expression類似於它與完成的方式length ,它編譯並正常工作。 normalize的獨立版本也可以正常工作。 我將normalize定義為類成員有什么問題?

謝謝!

如果我改變,它編譯並正常工作

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

在類Expression

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

但是,我不明白為什么這是必要的。 normalize的獨立聲明使用以前的decltype樣式並正常工作, Vector<double>繼承自Expression<Vector<double>,double> ,所以我不明白為什么我必須進行此更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM