Although I\'m doubtful, I\'m curious as to whether it\'s possible to extract primitive-type template parameters from an existing type, perhaps using RTTI.
For exampl
As stated by other answers, for std::bitset
you can get the size by using the size()
member function, which should be the right choice, better than any other trick.
There were several proposals for the generic case, almost similar to the one I suggest below, but still I think this one is simpler:
template <template<std::size_t> typename T, std::size_t K>
auto extractSize(const T<K>&) {
return K;
}
int main() {
std::bitset<6> f1;
std::bitset<13> f2;
std::cout << extractSize(f1) << std::endl;
std::cout << extractSize(f2) << std::endl;
}
In the case of std::bitset
, you can just use the size()
member function:
size_t sz = oh_my_word.size(); // sz is now 16
In the general case, you can define a member function which returns the size in a similar manner:
template <int N>
class Foo
{
public:
int size() const { return N; }
};
You can easily do this in C++11 using argument deduction and unevaluated contexts (note that demo uses C++14's variable template feature for convenience).
#include <type_traits>
#include <iostream>
template<int>
struct foo {};
template<int arg_N>
struct val {
static constexpr auto N = arg_N;
};
template<template <int> typename T, int N>
constexpr auto extract(const T<N>&) -> val<N>;
template<typename T>
constexpr auto extract_N = decltype(extract(std::declval<T>()))::N;
int main() {
std::cout << extract_N<foo<5>>;
}
Live demo
It's not possible in general to pick arbitrary template parameters.
However, the usual way you do it is this:
template<int N>
struct foo {
static const int value = N;
};
and for types
template<typename T>
struct foo {
typedef T type;
};
You can access it then as foo<39>::value
or foo<int>::type
.
If you have a particular type, you can use partial template specialization:
template<typename>
struct steal_it;
template<std::size_t N>
struct steal_it< std::bitset<N> > {
static const std::size_t value = N;
};
The same principle is possible for type parameters too, indeed. Now you can pass any bitset to it, like steal_it< std::bitset<16> >::value
(note to use size_t, not int!). Because we have no variadic many template paramters yet, we have to limit ourself to a particular parameter count, and repeat the steal_it template specializations for count from 1 up to N. Another difficulty is to scan types that have mixed parameters (types and non-types parameters). This is probably nontrivial to solve.
If you have not the type, but only an object of it, you can use a trick, to still get a value at compile time:
template<typename T>
char (& getN(T const &) )[steal_it<T>::value];
int main() {
std::bitset<16> b;
sizeof getN(b); // assuming you don't know the type, you can use the object
}
The trick is to make the function template auto-deduce the type, and then return a reference to a character array. The function doesn't need to be defined, the only thing needed is its type.
I like Marc Garcia's answer because it shows how to extract the template parameter in a generic way, but I believe his example can be simpler:
#include <type_traits>
#include <iostream>
template<int>
struct MyType {};
template<template <int> typename T, int N>
constexpr int extract(const T<N>&) { return N; }
int main() {
constexpr MyType<5> myObj;
std::cout << extract(myObj);
}
Live demo