Проверьте, имеют ли два типа один и тот же шаблон - PullRequest
2 голосов
/ 28 марта 2019

Я хочу проверить, относятся ли два типа к одному шаблону. В качестве примера я хочу, чтобы следующий фрагмент кода возвращал true, поскольку оба объекта являются векторами, несмотря на то, что внутренние элементы имеют разные типы.

Важно, чтобы проверка производилась во время компиляции (поэтому функция является 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);
}

Ответы [ 3 ]

2 голосов
/ 28 марта 2019

Вот, пожалуйста:

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

Демонстрация: http://coliru.stacked -crooked.com / a / 8533c694968f4dbb


Это работает, предоставляя специализацию are_same_template, которая отбрасывает типы аргументов шаблона:

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

Даже если T1 и T2 различаются (типы аргументов шаблона), are_same_template является истинным типом:

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

О template<class...> вместо template<class>: это должно учитывать тот факт, что std:: контейнеры имеют неявные аргументы шаблона. Спасибо ConstantinosGlynos за сообщение об этом.

0 голосов
/ 28 марта 2019

Вы можете, но это займет немного 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;
}

пробег: https://wandbox.org/permlink/OTuQfl7UBlbxgtCO

Обновление: вам нужен "шаблон класса Container1, class ...", потому что vector не принимает 1 параметр шаблона, а 2. В общем случае вы не знаете, сколько параметров по умолчанию будет использоваться

0 голосов
/ 28 марта 2019

Отметьте пост . Они предоставляют способ проверить, является ли что-то специализацией шаблонного класса:

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 {};

И, вероятно, сделайте что-то подобное, чтобы сохранить ваш оригинальный интерфейс:

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

Так что вы можете сделать что-то вроде этого:

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

...