Reputation: 2041
I have a small C++ class which wraps type information for some basic types; a simplified version looks like this:
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");
This works - but I would love to be able to instantiate the TypeInfo
object based on normal C++ templating; i.e. something like this:
TypeInfo<double> double_info; // <- This does not work
Since the class as such does not contain any T
- it is not really a templated class - but rather a convenient instantiation method. When this is contained in a function which is truly templated:
void vector_operation(const std::vector<T>& data) {
TypeInfo<T> type_info; // <- This does not work!
}
it would be really helpful if I could instantiate TypeInfo
instance based on a template parameter. Since I only need to cover a handful of fundamental types - float, double, int
and char
I would be more than happy to specialize the handful of types explicitly.
Update: @nathan_oliver suggested to make the class as a whole a template, and then use sizeof(T)
to determine the element size. The problem with that solution (as I see it) - is that the user still needs to supply the type_name
string (and some more type specific information) - I would like specialize the few types I need - and then fully specify:
template <typename T>
struct TypeInfo {
TypeInfo();
std::size_t elm_size;
std::string type_name;
}
And then in the .cpp file:
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";
}
but this does not even compile:
type_info.cpp:46:5: error:
invalid use of template-name ‘TypeInfo’ without an argument list
TypeInfo::TypeInfo()
Upvotes: 3
Views: 644
Reputation: 12978
If you're indeed only interested in a handful of fundamental types, and can specialize them manually it seems like a good way to go.
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
Then you can go ahead and use it by just instantiating with a template parameter.
If the fact that different instatiations of TypeInfo
are different types is a problem, you could use a function that return a common TypeInfo
object with the right values set based on the parameter passed to the function.
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>();
Upvotes: 1
Reputation: 181027
You can't make the class constructor a template and be able to specify the template type since you can't call a constructor.
You could make the class a template, and use the template type to get the size of the type instead of having it provided by the user. That would give you
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");
Upvotes: 0
Reputation: 41840
You cannot specify template parameters for a constructor. They can only be deduced. You could send a type tag to your constructor:
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>};
You'll have to find a way to get the name of a type from a template argument. Some libraries exists for that like ctti
Upvotes: 2
Reputation: 206717
Another solution is to use a helper function.
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);
}
and use
TypeInfo double_info = make_TypeInfo<double>("double");
TypeInfo int_info = make_TypeInfo<int>("int");
Upvotes: 0