Создание экземпляра не шаблонного класса с помощью шаблонного конструктора - PullRequest
2 голосов
/ 06 марта 2019

У меня есть небольшой класс C ++, который упаковывает информацию о типах для некоторых основных типов;упрощенная версия выглядит следующим образом:

struct TypeInfo {
    TypeInfo(std::size_t elm_size, const std::string& type_name) : 
        elm_size(elm_size), 
        type_name(type_name)
    {}

    std::size_t elm_size;
    std::string type_name;    
}


TypeInfo double_info(sizeof double, "double");
TypeInfo int_info(sizeof int, "int");

Это работает, но я бы хотел иметь возможность создания экземпляра объекта TypeInfo на основе нормальных шаблонов C ++;то есть что-то вроде этого:

TypeInfo<double> double_info; // <- This does not work

Поскольку класс как таковой не содержит никакого T - это на самом деле не шаблонный класс, а скорее удобный метод создания экземпляров.Когда это содержится в действительно шаблонной функции:

void vector_operation(const std::vector<T>& data) {
    TypeInfo<T> type_info;  // <- This does not work!
}

, было бы действительно полезно, если бы я мог создать экземпляр TypeInfo на основе параметра шаблона.Так как мне нужно охватить лишь несколько фундаментальных типов - float, double, int и char, я был бы более чем рад специализовать несколько типов явно.

Обновление : @nathan_oliver предложил сделать класс в целом шаблоном, а затем использовать sizeof(T) для определения размера элемента.Проблема с этим решением (как я его вижу) - это то, что пользователю все еще нужно предоставить строку type_name (и некоторую дополнительную информацию о типе) - я хотел бы специализировать несколько нужных мне типов - и затем полностью указать:

template <typename T>
struct TypeInfo {
    TypeInfo();

    std::size_t elm_size;
    std::string type_name;
}

А затем в файле .cpp:

template<>
TypeInfo::TypeInfo<double>() {
     this->elm_size = sizeof(double);
     this->type_name = "double";
}


template<>
TypeInfo::TypeInfo<int>() {
    this->elm_size = sizeof(int);
    this->type_name = "int";
}

, но это даже не компилируется:

type_info.cpp:46:5: error: 
invalid use of template-name ‘TypeInfo’ without an argument list
     TypeInfo::TypeInfo()

Ответы [ 4 ]

1 голос
/ 06 марта 2019

Если вы действительно интересуетесь лишь несколькими базовыми типами и можете специализировать их вручную, это кажется хорошим вариантом.

template <typename T>
struct TypeInfo; // default values could go here for un-specified types

template <>
struct TypeInfo<int> {
    const std::size_t elm_size = sizeof(T);
    const std::string type_name = "int";
}

// more specializations for double, char and float

Тогда вы можете пойти дальше и использовать его, простосоздание экземпляра с параметром шаблона.

Если проблема состоит в том, что различные установки TypeInfo являются разными типами, вы можете использовать функцию, которая возвращает общий объект TypeInfo с правильными значениями, установленными на основепараметр передан функции.

template <typename T>
TypeInfo get_type_info() {
    return TypeInfo{sizeof(T), "unknown"};
}

template <>
TypeInfo get_type_info<int>() {
    return TypeInfo{sizeof(T), "int"};
}

auto type_info = get_type_info<int>();
0 голосов
/ 06 марта 2019

Вы не можете указать параметры шаблона для конструктора. Они могут быть только выведены. Вы можете отправить тег типа вашему конструктору:

template<typename> struct tag_t {};
template<typename T> inline constexpr auto tag = tag_t<T>{}; 

struct TypeInfo {
    template<typename T>
    TypeInfo(tag_t<T>) :
        elm_size{sizeof(T)},
        type_name{/* find a way to get name */} {}

    std::size_t elm_size;
    std::string type_name;  
};

TypeInfo double_info{tag<double>};
TypeInfo int_info{tag<int>};

Вам нужно будет найти способ получить имя типа из аргумента шаблона. Для этого существует несколько библиотек, например ctti

0 голосов
/ 06 марта 2019

Другое решение - использовать вспомогательную функцию.

struct TypeInfo {
    TypeInfo(std::size_t elm_size, const std::string& type_name) : 
        elm_size(elm_size), 
        type_name(type_name)
    {}

    std::size_t elm_size;
    std::string type_name;    
};

template <typename T>
TypeInfo make_TypeInfo(const std::string& type_name)
{
   return TypeInfo(sizeof(T), type_name);
}

и используйте

TypeInfo double_info = make_TypeInfo<double>("double");
TypeInfo int_info = make_TypeInfo<int>("int");
0 голосов
/ 06 марта 2019

Вы не можете сделать конструктор класса шаблоном и иметь возможность указать тип шаблона, так как вы не можете вызвать конструктор.

Вы можете сделать класс шаблоном и использовать тип шаблона, чтобы получить размер типа вместо того, чтобы предоставить его пользователю. Это дало бы вам

template<typename T>
struct TypeInfo {
    TypeInfo(const std::string& type_name) : 
        type_name(type_name)
    {}

    std::size_t elm_size = sizeof(T);
    std::string type_name;    
};

TypeInfo<double> double_info("double");
TypeInfo<int> int_info("int");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...