«Не удалось вывести аргумент шаблона», если указан аргумент шаблона - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь написать свою собственную простую систему отражения на C ++. У меня есть следующий тестовый код:

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

Я сталкиваюсь с проблемами на TypeResolver<int>::get(), со следующими ошибками:

ошибка C2672: 'DefaultResolver :: get' : не найдено соответствующей перегруженной функции
примечание: при компиляции функции-члена шаблона класса 'TypeDescriptor * TypeResolver :: get (void)'
примечание: см. ссылку на создание экземпляра шаблона функции 'TypeDescriptor * TypeResolver :: get (void)' в процессе компиляции
примечание: см. ссылку на экземпляр шаблона класса 'TypeResolver', который компилируется
ошибка C2783: 'TypeDescriptor * DefaultResolver :: get (void)': не удалось вывести аргумент шаблона для '__formal'
примечание: см. объявление «DefaultResolver :: get»

Меня особенно смущает вторая ошибка. Я указываю аргумент шаблона, так чего мне не хватает?

1 Ответ

1 голос
/ 20 марта 2020

Две проблемы:

  1. std::enable_if не имеет ::value типа элемента, только ::type тип элемента, который присутствует, когда условие истинно.

  2. В return DefaultResolver::get<T>() предоставление явных аргументов шаблона отключает вывод аргументов шаблона для тех параметров, которые для работы std::enable_if зависят от .

Итак, сначала измените ::value в объявлениях std::enable_if на ::type. Следующая проблема будет состоять в том, чтобы позволить вывод аргумента шаблона работать при предоставлении типа шаблона. Вы можете сделать это, передав шаблон помощника в качестве аргумента функции, и в объявлении DefaultResolver::get() измените ваши параметры, чтобы принимать объекты этого типа класса:

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>{});
  }
};

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...