简体   繁体   中英

"Could not deduce template argument" when template argument is specified

I am attempting to write my own simple reflection system in C++. I have the following test code:

#include <cstdio>
#include <xtr1common>

// common base class
struct TypeDescriptor { };

// specialization for primitive types
template<class T>
struct Primitive : public TypeDescriptor
{
    static Primitive<T> Instance;
};
Primitive<int> Primitive<int>::Instance;

struct ReflectedType
{
    static TypeDescriptor Reflection;
};

// gets an appropriate TypeDescriptor for a type based on whether it has a Reflection member or not.
// if not, then it expects a Primitive<T> specialization
struct DefaultResolver
{
    // used to calculate IsReflected meta-function
    template<class T> static char func(decltype(&T::Reflection));
    template<class T> static int func(...);
    template<class T>
    struct IsReflected
    {
        enum
        {
            value = (sizeof(func<T>(nullptr)) == sizeof(char))
        };
    };

    // get the TypeDescriptor for a reflected class
    template<class T, typename std::enable_if<IsReflected<T>::value, int>::value = 0>
    static TypeDescriptor* get()
    {
        return &T::Reflection;
    }

    // get the TypeDescriptor for a Primitive<T> if it is not reflected
    template<class T, typename std::enable_if<!IsReflected<T>::value, int>::value = 0>
    static TypeDescriptor* get()
    {
        return &Primitive<T>::Instance;
    }
};

// helper class that provides type-safe access to a type's TypeDescriptor
template<class T>
struct TypeResolver
{
    static TypeDescriptor* get()
    {
        return DefaultResolver::get<T>();
    }
};

int main()
{
    // no problems here, obviously
    TypeDescriptor* desc = &Primitive<int>::Instance;

    // resolves to false, as expected
    constexpr bool isIntReflected = DefaultResolver::IsReflected<int>::value;

    // resolves to true, as expected
    constexpr bool isClassReflected = DefaultResolver::IsReflected<ReflectedType>::value;

    // this does not compile
    desc = TypeResolver<int>::get();

    getchar();
    return 0;
}

I am running into issues at the TypeResolver<int>::get() , with the following errors:

error C2672: 'DefaultResolver::get': no matching overloaded function found
note: while compiling class template member function 'TypeDescriptor *TypeResolver::get(void)'
note: see reference to function template instantiation 'TypeDescriptor *TypeResolver::get(void)' being compiled
note: see reference to class template instantiation 'TypeResolver' being compiled
error C2783: 'TypeDescriptor *DefaultResolver::get(void)': could not deduce template argument for '__formal'
note: see declaration of 'DefaultResolver::get'

I am particularly confused by the second error. I am specifying the template argument, so what am I missing?

Two issues:

  1. std::enable_if does not have a ::value member type, only a ::type member type which is present when the condition is true.

  2. In return DefaultResolver::get<T>() , providing explicit template arguments disables template argument deduction for those parameters, which what the std::enable_if is depending on in order to work.

So first change ::value in the std::enable_if declaractions to ::type . The next problem would be to allow template argument deduction to work while providing the template type. You can do this by passing a helper template as a function argument, and in the declaration of DefaultResolver::get() change your parameters to accept objects of that class type:

template <class T>
struct type_t { };
// ...
template <class T,
          typename std::enable_if<IsReflected<T>::value, int>::type = 0>
static TypeDescriptor* get(type_t<T>);

template <class T,
          typename std::enable_if<!IsReflected<T>::value, int>::type = 0>
static TypeDescriptor* get(type_t<T>);
// ...
template <class T>
struct TypeResolver
{
  static TypeDescriptor* get()
  {
    return DefaultResolver::get(type_t<T>{});
  }
};

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM