Anthony
Anthony

Reputation: 1133

Way to deduce if type is from a templated class

I've been trying to answer the question in the title, but I'm stumped. Basically, trying to see if there's a built-in way to tell the 'source' of a template instantiation, at least for classes. Here is an example of what I'd like to do:

template<class T>
class A { };

auto a = A<int>();

template<class T>
auto someFunction(T item) {
    if(/* if type of a is from the templated class A */) {
        // yep A<int> is 'from' A.
    }
}

Is this possible, in some way such as this? I could use some saved value or inheritance shenanigans to get something similar, but I'd rather not.

Upvotes: 0

Views: 82

Answers (3)

Jarod42
Jarod42

Reputation: 218238

An other way, allowing derived class to match:

template <typename T>
std::true_type is_an_A_impl(A<T>*);

std::false_type is_an_A_impl(...);

template <typename T>
using is_a_A = decltype(is_an_A_impl(std::declval<T*>()));

Upvotes: 1

max66
max66

Reputation: 66230

Maybe with a custom type traits.

Something as follows

template <typename>
struct is_A : public std::false_type
 { };

template <typename T>
struct is_A<A<T>> : public std::true_type
 { };

// ...

template <typename T>
auto someFunction(T item) {
   if( is_A<T>::value ) {
    // yep A<int> is 'from' A.
   }
}

Or, maybe, you want intercept non only A<T> but, generically, all types that are a template type, maybe with an undefined number of template arguments?

In this case you can try with something as follows

template <typename>
struct is_template : public std::false_type
 { };

template <template <typename...> class C, typename ... Ts>
struct is_template<C<Ts...>> : public std::true_type
 { };

Problem: this type traits intercepts all template types with types template arguments and only template arguments. But doesn't intercept, by example, std::integer_sequence<int, 0, 1, 2, 3, 4, 5> that receive a type and some non-type template parameter.

You can add other specializations for is_template, to intercept other cases, but you can't define a specialization that catch all template types (all combinations of template parameters).

Upvotes: 4

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123253

Use a type trait

#include <type_traits>
#include <iostream>

template<class T>
class A { };

auto a = A<int>();

template <typename X>
struct is_from_A : std::false_type {};

template <typename T>
struct is_from_A<A<T>> : std::true_type {};

int main() {
    std::cout << is_from_A<int>::value << "\n";     // 0
    std::cout << is_from_A<A<int>>::value << "\n";  // 1
}

Upvotes: 1

Related Questions