Code:
#include <iostream>
template<typename T>
class MyRNG{
public:
T Rand(){return T();};
};
template<typename RNG, typename = void>
struct GetDataTypeOf;
template<typename RNG>
struct GetDataTypeOf<RNG, decltype(std::declval<RNG>().Rand())> {
typedef decltype(std::declval<RNG>().Rand()) type;
};
template<typename RNG>
using DataTypeOf = typename GetDataTypeOf<RNG>::type;
int main(){
std::cout << typeid(DataTypeOf<MyRNG<int>>).name() << std::endl;
}
Error:
incomplete type is not allowed
using DataTypeOf = typename GetDataTypeOf<RNG>::type;
^
detected during instantiation of type "DataTypeOf<MyRNG<int>>" at line 22
It seems that GetDataTypeOf<MyRNG<int>>
does not match any of the specialized class definitions. Why could that be?
Compiler: gcc 9.4.0
The problem is that decltype(std::declval<RNG>().Rand())
is not void
. This means that you've provided the specialization not for void
but for the return type T
.
One way to solve this is to add void
to do explicit conversion so that the specialization becomes a specialization for void
as shown below:
template<typename RNG>
//---------------------------------vvvv-------------------------->added void here
struct GetDataTypeOf<RNG, decltype(void(std::declval<RNG>().Rand()))> {
typedef decltype(std::declval<RNG>().Rand()) type;
};