使用模板化构造函数实例化非模板类

时间:2019-03-06 19:28:31

标签: c++ templates

我有一个小的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");

这有效-但我希望能够基于常规C ++模板实例化TypeInfo对象;即是这样的:

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, intchar,所以我很乐意显式地专门化少数几个类型。

更新:@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 个答案:

答案 0 :(得分:1)

如果您确实只对少数几个基本类型感兴趣,并且可以手动对其进行专门化,那似乎是个不错的选择。

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>();

答案 1 :(得分:0)

由于不能调用构造函数,因此不能将类构造函数用作模板,也不能指定模板类型。

您可以将类设为模板,并使用模板类型获取类型的大小,而不是由用户提供。那会给你

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");

答案 2 :(得分:0)

您不能为构造函数指定模板参数。他们只能被推论。您可以将类型标签发送到构造函数:

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

答案 3 :(得分:0)

另一种解决方案是使用辅助函数。

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");