Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract C++ template parameters

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++.

like image 265
cdleary Avatar asked Nov 19 '08 06:11

cdleary


People also ask

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

Can template parameters have default values?

Template parameters may have default arguments. The set of default template arguments accumulates over all declarations of a given template.

What are template parameters?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.

Which template can have multiple parameters?

Explanation of the code: In the above program, the Test constructor has two arguments of generic type. The type of arguments is mentioned inside angle brackets < > while creating objects.


2 Answers

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.

like image 76
Johannes Schaub - litb Avatar answered Oct 17 '22 05:10

Johannes Schaub - litb


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

like image 23
Mark Garcia Avatar answered Oct 17 '22 04:10

Mark Garcia