views:

751

answers:

2

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 example:

typedef std::bitset<16> WordSet;

Would it be possible to extract the number 16 in the above code without hard-coding it elsewhere? Compiler specific implementations are welcome, though I'm particularly interested in g++.

+1  A: 

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; }
};
Adam Rosenfield
I'm talking about extracting it from third-party classes with no `size()` method or anything similar -- extracting it just knowing the type itself. The reason being that I don't want to have to make a dummy instance just to get the size of the typedef'd bitset.
cdleary
It's not a particularly bad penalty for bitset, but there could be other types where instantiating a dummy type is undesirable or impractical.
cdleary
+12  A: 

It's not possible. 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.

Johannes Schaub - litb
Nice trick. One thing though, you start by saying how it's not possible, but then proceed to show that it is! :)
Richard Corden
@Richard Corden: I think he was saying it's not possible to do using RTTI
cdleary
Richart Corden. I meant it's generally not possible to pick arbitrary template parameters. consider this: template<template<class, int> class, class, size_t> class foo; that trick won't get their types :)
Johannes Schaub - litb