Is it possible to capture a template from a template argument i.e. have a nested template specifier with a template argument that holds the template type?
template< typename T, typename Label = std::string>
class foo {
// ...
};
template <
template < typename C, typename T > typename C<T>,
// ...
typename Label = std::string
>
class bar {
// ...
C< foo< T, Label > > A;
};
For instance, I'd like to pass a generic STL container (std::vector< int >
) as template argument, but declare a member of the same meta-type (std::vector
) but with different value type (foo< int >
) i.e. std::vector< foo< int > >
. It may seem convoluted, but it would be helpful to not hardcode the type of STL container.
For context, I'm aiming at a generic container adapter/wrapper (in the line of std::stack
or std::queue
) that provides some higher-level functionality.
CodePudding user response:
Yes, you can just use template specialization:
#include <string>
template<typename T, typename Label = std::string>
class foo {};
template <class T, typename Label = std::string>
class bar;
template <template<class...> class C, typename T, typename Label>
class bar<C<T>, Label> {
C<foo<T, Label>> A;
};
CodePudding user response:
The other answer's approach can be generalized as a reusable template rebinder:
template<typename T>
struct rebinder;
template<template<typename...> typename T, typename... Args>
struct rebinder<T<Args...>> {
template<typename... Us>
using rebind = T<Us...>;
};
template<typename T, typename... Us>
using rebound = rebinder<T>::template rebind<Us...>;
// example:
#include <vector>
template<typename T>
struct MyStruct {
rebound<T, float> vec;
};
int main() {
MyStruct<std::vector<int>> x;
static_assert(std::is_same_v<std::vector<float>, decltype(x.vec)>);
}
see on godbolt