Reputation: 8975
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?
Upvotes: 4
Views: 968
Reputation: 1947
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
Upvotes: 0
Reputation: 283684
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.
Upvotes: 0
Reputation: 96810
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))>
Upvotes: 11
Reputation: 490148
You need/want std::declval
:
decltype(std::declval<ValueType>()+std::declval<CompatibleType>());
Upvotes: 6
Reputation: 16046
You could use std::declval
for that:
decltype(std::declval<A>()+std::declval<B>))
Upvotes: 6