c++templatestemplate-specialization

Why does my template specialization fail to compile?


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


Solution

  • 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;
    };
    
    

    Demo