get first template parameter of a class - c++

I have a class foo which takes two template parameters, what I want to do is defaulting the second parameter to the first template parameter of the first parameter if it exists. foo would look like
template<typename Class, typename T = typename first_template_parameter<Class>::type>
class foo
{
...
}
and if Class has been defined as template<typename A, typename B, ...> class bar I want T to be A. So for example foo<std::map<int, float>> would have Class = std::map<int, float> and T = int, foo<int, char> would have Class = int and T = char. How can I implement first_template_parameter?

Drilling down into the first template parameter requires a little bit of work involving specialization:
template<typename T> struct first_template_type;
template<template<typename T, typename ...> class t,
typename T, typename ...Args>
struct first_template_type<t<T, Args...>> {
typedef T type_t;
};
template<typename T>
using first_template_type_t=typename first_template_type<T>::type_t;
Once that's out of the way, the rest is pretty boring:
#include <map>
template<typename Class,
typename T = first_template_type_t<Class>>
class foo
{
public:
T bar;
};
foo<std::map<int, char>> Foo;
int *baz=&Foo.bar;

Related

Is it possible to capture a type template into a template argument?

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.
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;
};
Demo.
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

How to create template class with member function pointer?

Is anyone knows how to declare generalized template form for the next template specialization:
template <template <class> class Container,
class Value,
class Return,
Return (Container<Value>::*Apply)(const Value &)>
class Example<Container<Value>, Apply>
{
};
Apply must be a pointer to a member function whoes signature is unknown in template declaration.
Do you mean something like this?
template<typename T, typename F>
struct S;
template<template <typename...> class C, typename R, typename... A>
struct S<C<A...>, R(A...)> {
using Apply = R(C<A...>::*)(A...);
// ...
};
As an example:
template<typename... U>
struct T {
int f(int, char) { return 42; }
};
template<typename T, typename F>
struct S;
template<template <typename...> class C, typename R, typename... A>
struct S<C<A...>, R(A...)> {
using Apply = R(C<A...>::*)(A...);
// ...
};
int main() {
S<T<int, char>, int(int, char)>::Apply apply = &T<int, char>::f;
}
Pretty ugly, indeed, but that's what the OP (maybe) asked.

Accessing template arguments from specialization

template<typename T, typename U>
struct A;
template<std::size_t I>
struct A<int, char[I]> {
using pointer = T*; // does not compile
};
int main() {
A<int, char[3]> a;
}
Is there any way to access the type T (= int) from inside the class template specialization A<int, char[I]>, without explicitly writing the type that is has in the specialization?
Something like this:
template<class T, class U, class=T, class=U>
struct A;
template<std::size_t I, class T, class U>
struct A<int, char[I], T, U> {
using pointer = T*;
};
works. If someone actually passes a type for the second T and U problems develop, but...
Another approach is:
template<class T, class U>
struct A;
// get args from an instance!
template<class A>
struct A_Args;
template<class T_, class U_>
struct A_Args<A<T_,U_>> {
using T = T_; using U = U_;
};
template<class A>
using A_T = typename A_Args<A>::T;
template<class A>
using A_U = typename A_Args<A>::U;
// reflect on our troubles:
template<std::size_t I>
struct A<int, char[I]> {
using pointer = A_T<A>*;
};
where we have a using alias that extracts args from a generic A which we use within the specialization.
This version can be made generic with an interface like:
template<std::size_t I, class Instance>
struct nth_template_arg;
template<std::size_t I, class Instance>
using nth_template_arg_t=typename nth_template_arg<I, Instance>::type;
with the note it will only work with templates that only take type arguments. (implementation left as an exercise. I'd probably use tuple_element for a first pass; using tuples has the downside that they are heavy types, and metaprogramming with heavy types sucks performance and sometimes causes other problems.)
Simply,
#include <type_traits>
template<class T, class U>
struct foo;
template<class T, std::size_t Index>
struct foo<T, char[Index]>
{
using type = T;
};
int
main()
{
static_assert(std::is_same<foo<int, char[3]>::type, int>::value, "");
}
You can try this:
template<typename T, typename U, std::size_t I>
struct A{
using pointer = T*;
};

Altering template template parameters in C++

I would like to design a class that creates internal types that are variants of types passed as template parameters. Something like the following, non-functional example:
template <typename T>
class BaseClass
{
public:
typedef T InternalType;
std::vector<InternalType> storage;
};
template <typename Base>
class Injector
{
public:
typedef std::pair<typename Base::InternalType, typename Base::InternalType> RefinedType;
Base<RefinedType> refinedStorage;
};
typedef Injector<BaseClass<int> > InjectedInt; // Should store vector<pair<int, int> >
Since Base is a fully-specified type, Base<RefinedType> refinedStorage; will fail to compile. Simply using a template template parameter won't work, as the refined type needs to be based on the nested template's parameter as well as its base type.
How can I implement this pattern of creating types based on both the fully-specified and base types of a template parameter?
EDIT: I would like this to be an arbitrary-depth composite, with multiple injector types performing a cascade of transformations. Thus, passing both the template template parameter and the base parameter becomes pretty unwieldy (particularly when it comes to dealing with the base case of the composite), and an ideal solution would use the more direct syntax.
I was able to achieve this by explicitly 're-declaring' the general template inside itself:
template <typename T>
class BaseClass
{
public:
typedef T InternalType;
std::vector<InternalType> storage;
template<class T2>
using Recur = BaseClass<T2>;
};
template <typename Base>
class Injector
{
public:
typedef std::pair<typename Base::InternalType, typename Base::InternalType> RefinedType;
typename Base::template Recur<RefinedType> refinedStorage;
};
typedef Injector<BaseClass<int> > InjectedInt; // Should store vector<pair<int, int> >
You could introduce a rebind template:
template <typename From, typename To>
struct rebind_1st;
template <template <typename... > class Cls, typename A0, typename... Args, typename To>
struct rebind_1st<Cls<A0, Args...>, To> {
using type = Cls<To, Args...>;
};
template <typename From, typename To>
using rebind_1st_t = typename rebind_1st<From, To>::type;
With which your Injector becomes:
template <typename Base>
class Injector
{
public:
typedef std::pair<typename Base::InternalType,
typename Base::InternalType> RefinedType;
rebind_1st_t<Base, RefinedType> refinedStorage;
};
There is no need for a rebinding template, that over-complicates the situation. Simply have a template template type:
template<typename>
struct Injector;
template<typename T, template<typename> class Base>
struct Injector<Base<T>>{
using refined_type = std::pair<typename Base::InternalType, typename Base::InternalType>;
Base<refined_type> refined_storage;
};
You'll have to use a template specialization to get a concrete type from a template template.
This is used like so:
using injector_int = Injector<Base<int>>;
int main(){
injector_int i;
}
here's a live example
You can provide an external rebinder:
template <class Bound, class U>
struct rebinder;
template <template <class> class Binder, class B, class U>
struct rebinder<Binder<B>, U>
{
typedef Binder<U> type;
};
// Usage:
template <typename Base>
class Injector
{
public:
typedef std::pair<typename Base::InternalType, typename Base::InternalType> RefinedType;
typename rebinder<Base, RefinedType>::type refinedStorage;
};
[Live example]

Conditional compile-time inclusion/exclusion of code based on template argument(s)?

Consider the following class, with the inner struct Y being used as a type, eg. in templates, later on:
template<int I>
class X{
template<class T1>
struct Y{};
template<class T1, class T2>
struct Y{};
};
Now, this example will obviously not compile, with the error that the second X<I>::Y has already been defined or that it has too many template parameters.
I'd like to resolve that without (extra) partial specialization, since the int I parameter isn't the only one and the position of it can differ in different partial specializations (my actual struct looks more like this, the above is just for simplicity of the question), so I'd like one class fits every I solution.
My first thought was obviously enable_if, but that seems to fail on me, eg. I still get the same errors:
// assuming C++11 support, else use boost
#include <type_traits>
template<int I>
class X{
template<class T1, class = std::enable_if<I==1>::type>
struct Y{};
template<class T1, class T2, class = std::enable_if<I==2>::type>
struct Y{};
};
So, since enable_if fails, I hope there is another way to achieve the following compile time check:
template<int I>
class X{
__include_if(I == 1){
template<class T1>
struct Y{};
}
__include_if(I == 2){
template<class T1, class T2>
struct Y{};
}
};
It would just be to save me a lot of code duplication, but I'd be really happy if it was somehow possible.
Edit: Sadly, I can't use the obvious: variadic templates, as I'm using Visual Studio 2010, so only the C++0x stuff that is supported there I can use. :/
There are two problems here:
enable_if works with partial specialization, not primary templates.
The number of externally-visible arguments is determined by the primary template, of which there may be only one.
Answer 1.
As you suggested in chat, a linked list of templates can emulate the variadic parameter pack.
template<int I>
class X{
template<class list, class = void>
struct Y;
template<class list>
struct Y< list, typename std::enable_if<I==1>::type > {
typedef typename list::type t1;
};
template<class list>
struct Y< list, typename std::enable_if<I==2>::type > {
typedef typename list::type t1;
typedef typename list::next::type t2;
};
};
If you end up with next::next::next garbage, it's easy to write a metafunction, or use Boost MPL.
Answer 2.
The different-arity templates can be named similarly but still stay distinct if they are nested inside the SFINAE-controlled type.
template<int I>
class X{
template<typename = void, typename = void>
struct Z;
template<typename v>
struct Z< v, typename std::enable_if<I==1>::type > {
template<class T1>
struct Y{};
};
template<typename v>
struct Z< v, typename std::enable_if<I==2>::type > {
template<class T1, class T2>
struct Y{};
};
};
X<1>::Z<>::Y< int > a;
X<2>::Z<>::Y< char, double > b;
Here you go:
http://ideone.com/AdEfl
And the code:
#include <iostream>
template <int I>
struct Traits
{
struct inner{};
};
template <>
struct Traits<1>
{
struct inner{
template<class T1>
struct impl{
impl() { std::cout << "impl<T1>" << std::endl; }
};
};
};
template <>
struct Traits<2>
{
struct inner{
template<class T1, class T2>
struct impl{
impl() { std::cout << "impl<T1, T2>" << std::endl; }
};
};
};
template<class T>
struct Test{};
template<class T, class K>
struct Foo{};
template<int I>
struct arg{};
template<
template<class, class> class T,
class P1, int I
>
struct Test< T<P1, arg<I> > >{
typedef typename Traits<I>::inner inner;
};
template<
template<class, class> class T,
class P2, int I
>
struct Test< T<arg<I>, P2 > >{
typedef typename Traits<I>::inner inner;
};
// and a bunch of other partial specializations
int main(){
typename Test<Foo<int, arg<1> > >::inner::impl<int> b;
typename Test<Foo<int, arg<2> > >::inner::impl<int, double> c;
}
Explanation: Basically it's an extension of the idea of partial specialization, however the difference is that rather than specializing within Test, delegate to a specific class that can be specialized on I alone. That way you only need to define versions of inner for each I once. Then multiple specializations of Test can re-use. The inner holder is used to make the typedef in the Test class easier to handle.
EDIT: here is a test case that shows what happens if you pass in the wrong number of template arguments: http://ideone.com/QzgNP
Can you try below (it is not partial specialization):
template<int I>
class X
{
};
template<>
class X<1>
{
template<class T1>
struct Y{};
};
template<>
class X<2>
{
template<class T1, class T2>
struct Y{};
};
I doubt if the answer is that simple !!
Edit (Mocking Partial specialization):
#Xeo, I was able to compile following code and seems to be fullfilling.
template<int I>
struct X
{
struct Unused {}; // this mocking structure will never be used
template<class T1, class T2 = Unused> // if 2 params passed-->ok; else default='Unused'
struct Y{};
template<class T1>
struct Y<T1, Unused>{}; // This is specialization of above, define it your way
};
int main()
{
X<1>::Y<int> o1; // Y<T1 = int, T2 = Unused> called
X<2>::Y<int, float> o2; // Y<T1 = int, T2 = float> called
}
Here, however you can use X<1>, X<2> interchangeably. But in the broader example you mentioned, that is irrelevant. Still if you need, you can put checks for I = 1 and I = 2.
How about this approach - http://sergey-miryanov.blogspot.com/2009/03/template-class-overriding.html? (sorry for russian)
You can use a meta function (here: inlined boost::mpl::if_c, but could be arbitrarily complex) to select the one you want. You need some scaffolding to be able to use constructors, though:
template <int I>
class X {
template <typename T1>
class YforIeq1 { /* meat of the class */ };
template <typename T1, typename T2>
class YforIeq2 { /* meat of the class */ };
public:
template <typename T1, typename T2=boost::none_t/*e.g.*/>
struct Y : boost::mpl::if_c<I==1,YforIeq1<T1>,YforIeq2<T1,T2> >::type {
typedef typename mpl::if_c<I==1,YforIeq1<T1>,YforIeq2<T1,T2> >::type YBase;
/* ctor forwarding: C++0x */
using YBase::YBase;
/* ctor forwarding: C++03 (runs into perfect fwd'ing problem)*/
Y() : YBase() {}
template <typename A1>
Y(const A1&a1) : YBase(a1) {}
template <typename A1, typename A2>
Y(const A1&a1, const A2&a2) : YBase(a1,a2) {}
// ...
};
};
If there's a problem with both YforIeqN being instantiated for each X, then you can try wrapping them as a nullary meta function (something along the way mpl::apply does) and use mpl::eval_if_c.