Вопрос

With decltype I can do the following:

template <typename T1, typename T2>
auto sum(T1 const & t1, T2 const & T2)
-> decltype(t1+t2)
{ /* ... */ }

However, in my case I need to find out the type of an addition without having instances of the types T1 and T2. Concretely:

template <typename ValueType>
class Matrix
{
    /* ... */
    public:
        template <typename CompatibleType>
        auto operator+(Matrix<CompatibleType> const & other)
        -> Matrix<decltype(ValueType+CompatibleType)>
        { /* ... */ }
};

Of course, decltype(ValueType+CompatibleType) does not work this way. Is there any way I can achieve this?

Это было полезно?

Решение

Use std::declval<T>(); (C++11):

#include <utility>

template <typename CompatibleType>
 auto operator+(Matrix<CompatibleType> const & other)
  -> Matrix<decltype(std::declval<ValueType>() + std::declval<CompatibleType>())>
    { /* ... */ }

std::declval returns an rvalue-reference, and will only work in an unevaluated-context, which decltype happens to be.

If your compiler doesn't support this Standard, use this pointer trick (which also only works in an unevaluated-context):

-> Matrix<decltype(*(ValueType*)(0) + *(CompatibleType*)(0))>
// or
-> Matrix<decltype(*static_cast<ValueType*>(0) +
                   *static_cast<CompatibleType*>(0))>

Другие советы

You could use std::declval for that:

decltype(std::declval<A>()+std::declval<B>))

You need/want std::declval:

decltype(std::declval<ValueType>()+std::declval<CompatibleType>());

std::declval works, but there's a simpler answer hiding inside the ... -- real element access!

Assuming your Matrix class has an at function like std::vector, you can write

template<typename M>
auto operator+(M const & other)
     -> Matrix<decltype(this->at(0,0) + other.at(0,0))>

Otherwise, replace at with the correct function name which is used inside the operator+ body to access the individual elements.

This has the further advantage that it works on any other parameter which provides the needed accessor function, it doesn't have to be another Matrix<T> at all. That's called duck typing, and is why you should use the same accessor function that your function body actually uses.

A bit late to the party, but assuming ValueType and CompatibleType are POD types or other classes that have a public argument-free constructor (probably a valid assumption for your use-case), you can just construct those types. So

decltype(ValueType+CompatibleType)

does not work (as you wrote) but

decltype(ValueType() + CompatibleType())

does and there's no runtime overhead (Source: here). You don't need std::declval in this case.

Proof: Here

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top