Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is T an instance of a template in C++?

Tags:

c++

templates

Suppose I'm in a template and I want to know if a type parameter T is an instantiation of a particular template, e.g., std::shared_ptr:

template<typename T>
void f(T&& param)
{
    if (instantiation_of(T, std::shared_ptr)) ...   // if T is an instantiation of 
                                                    // std::shared_ptr...
  ...
}

More likely I'd want to do this kind of test as part of a std::enable_if test:

template<typename T>
std::enable_if<instantiation_of<T, std::shared_ptr>::type
f(T&& param) 
{
    ...
}

// other overloads of f for when T is not an instantiation of std::shared_ptr

Is there a way to do this? Note that the solution needs to work with all possible types and templates, including those in the standard library and in other libraries I cannot modify. My use of std::shared_ptr above is just an example of what I might want to do.

If this is possible, how would I write the test myself, i.e., implement instantiation_of?

like image 816
KnowItAllWannabe Avatar asked May 30 '12 17:05

KnowItAllWannabe


People also ask

How many templates are there in C?

There are three kinds of templates: function templates, class templates and, since C++14, variable templates.

What is the difference between template T and template typename T?

what's the difference between template <typename T> and template <class T>? Nothing actually. typename is a designated keyword for this purpose but class is supported for backwards compatibility and historical reasons (before typename keyword was added).

Which keyword can be used in template?

C++ adds two new keywords to support templates: 'template' and 'typename'. The second keyword can always be replaced by the keyword 'class'.

Is Vector a template?

vector is a template class, which can be instantiated with a type, in the format: vector<int> , vector<double> , vector<string> . The same template class can be used to handle many types, instead of repeatably writing codes for each of the type.


2 Answers

Why use enable_if when simple overloading suffices?

template<typename T>
void f(std::shared_ptr<T> param) 
{
    // ...
}

If you really do need such a trait, I think this should get you started (only roughly tested with VC++ 2010):

#include <type_traits>

template<typename>
struct template_arg;

template<template<typename> class T, typename U>
struct template_arg<T<U>>
{
    typedef U type;
};

template<typename T>
struct is_template
{
    static T* make();

    template<typename U>
    static std::true_type check(U*, typename template_arg<U>::type* = nullptr);
    static std::false_type check(...);

    static bool const value =
        std::is_same<std::true_type, decltype(check(make()))>::value;
};

template<
    typename T,
    template<typename> class,
    bool Enable = is_template<T>::value
>
struct specialization_of : std::false_type
{ };

template<typename T, template<typename> class U>
struct specialization_of<T, U, true> :
    std::is_same<T, U<typename template_arg<T>::type>>
{ };
like image 80
ildjarn Avatar answered Oct 18 '22 03:10

ildjarn


A partial spec should be able to do it.

template <template <typename...> class X, typename T>
struct instantiation_of : std::false_type {};

template <template <typename...> class X, typename... Y>
struct instantiation_of<X, X<Y...>> : std::true_type {};

http://ideone.com/4n346

I actually had to look up the template template syntax, because I've basically never had cause to use it before.

Not sure how this interacts with templates like std::vector with additional defaulted arguments.

like image 44
Puppy Avatar answered Oct 18 '22 04:10

Puppy