user28032019
user28032019

Reputation: 205

Check if two types are of the same template

I want to check if two types are of the same template. As an example I want the following snippet of code to return true because both objects are vectors despite the inner elements being of different types.

It's important that the check is made at compile time (that's why the function is constexpr).

#include <iostream>
#include <type_traits>
#include <vector>

template <typename Container1, typename Container2> constexpr bool CheckTypes(Container1 c1, Container2 c2)
{
    return std::is_same<Container1,Container2>::value;
}

int main()
{
  std::vector<int> v1(100,0);
  std::vector<double> v2(100,0);
  std::cout << CheckTypes(v1,v2);
}

Upvotes: 10

Views: 2526

Answers (4)

Sergey Kolesnik
Sergey Kolesnik

Reputation: 3640

In case you would like to check if two template template classes are the same without specializing them:

template<template<typename...> class ATT, template<typename...> class BTT>
struct is_same_tt : std::false_type {};

template<template<typename...> class TT>
struct is_same_tt<TT, TT> : std::true_type {};

// example
static_assert(is_same_tt<std::tuple, std::tuple>());
static_assert(!is_same_tt<std::vector, std::list>());

Upvotes: 2

YSC
YSC

Reputation: 40080

Here you go:

template <class T, class U>
struct are_same_template : std::is_same<T, U>
{};

template <template<class...> class T, class T1, class T2>
struct are_same_template<T<T1>, T<T2>> : std::true_type
{};

template <class T, class U>
constexpr bool CheckTypes(T, U)
{
    return are_same_template<T, U>::value;
}

Demo: http://coliru.stacked-crooked.com/a/8533c694968f4dbb


This works by providing a specialization of are_same_template that discard the template argument types:

template <template<class...> class T, class T1, class T2>
struct are_same_template<T<T1>, T<T2>>

Even if T1 and T2 differ (the template argument types), are_same_template is a true type:

are_same_template<T<T1>, T<T2>> : std::true_type

About template<class...> instead of template<class>: this is to accomodate the fact than std:: containers have implicit template arguments. Thanks to ConstantinosGlynos for making me aware of it.

Upvotes: 5

Martin Morterol
Martin Morterol

Reputation: 2870

You can but it take a little of metaprog :

#include <iostream>
#include <type_traits>
#include <vector>
#include <set>

template <typename Container1, typename Container2> 
struct CheckTypes_impl
{
    constexpr static bool check (Container1 , Container2 ) { return false; }
};

template <
    template <class...> class Container1, class...  args1 ,  class...  args2 > 
struct CheckTypes_impl<Container1<args1...>,Container1<args2...>>
{
    constexpr static bool check (Container1<args1...> , Container1<args2...> ) { return true; }
};


template < 
        template <class...> class Container1,
        class ... args1,
        template <class...> class Container2,
        class ... args2
    > constexpr bool CheckTypes(Container1<args1...> c1, Container2<args2...> c2)
{
    return CheckTypes_impl<Container1<args1...>,Container2<args2...>>::check(c1,c2);
}

int main()
{
  std::vector<int> v1(100,0);
  std::vector<double> v2(100,0);
  std::set<int> s;
  std::cout << CheckTypes(v1,v2)  << std::endl;
  std::cout << CheckTypes(v1,s)  << std::endl;
}

run : https://wandbox.org/permlink/OTuQfl7UBlbxgtCO

Update : You need " template class Container1, class..." because vector don't take 1 template param, but 2. In the general case you don't know how many default parameters will be used

Upvotes: 1

mohabouje
mohabouje

Reputation: 4050

Check this post. They provide a way to check if something is a specialization of a template class:

template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type {};

template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref>: std::true_type {};

And probably do something like this to keep your original interface:

template <typename Container1, typename Container2> 
constexpr bool CheckTypes(Container1 c1, Container2 c2) {
    return is_specialization<Container1, std::vector>::value && is_specialization<Container2, std::vector>::value;
}

So you can do something like this:

int main() {
    std::vector<int> v1(100,0);
    std::vector<double> v2(100,0);
    std::cout << CheckTypes(v1,v2);
    return 0;
}

Upvotes: 0

Related Questions