【问题标题】:Check if two types are of the same template检查两种类型是否属于同一个模板
【发布时间】:2019-03-28 10:14:00
【问题描述】:

我想检查两种类型是否属于同一个模板。举个例子,我希望下面的 sn-p 代码返回 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);
}

【问题讨论】:

  • 如果你需要在编译时检查某些东西,你应该使用静态类型而不是变量。
  • 但是它们的类型不一样...容器是一样的,不是实例化的类型。您可以使用sizeof 进行检查,但我不确定这样的解决方案有多优雅。
  • 我希望它适用于任何容器。
  • 为什么要检查这个?
  • @Sombrero 对 dup 不太满意。这个Q有点不同。 OP 以std::vector 为例,但他们的问题比这更笼统:“我想检查两种类型是否属于同一模板”。

标签: c++ sfinae typetraits


【解决方案1】:

给你:

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&lt;class...&gt; 而不是template&lt;class&gt;:这是为了适应std:: 容器具有隐式模板参数的事实。感谢 ConstantinosGlynos 让我意识到这一点。

【讨论】:

  • 我喜欢这种方法,但为什么在这里不起作用:rextester.com/LRJ63332
  • 我尝试使用 g++、vc++ 和 clang.. 都返回相同的结果。唯一的区别是 c++17 标志。 Godbolt 也返回 0。godbolt.org/z/tVKxiv
  • 我感觉Coliru 出了点问题。尝试了几个编译器和平台(rextester, ideone, Qt 和godbolt)。即使打开c++17 标志,所有结果都相同(false)。我认为Coliru 编译器正在发挥作用......
  • 我不这么认为...因为这意味着g++ 和vc++ 有相同的错误。 Coliru 也在使用g++。另外,我在想,std::vector 容器有一个用于std::allocator 的第二个模板参数。部分专业化不包括那个让我认为它不是被选中的参数。亲爱的(我是对的):rextester.com/MRXAQ82842
  • @YSC 您的回答很好,并且已被接受。你现在能帮我一个稍微不同的吗stackoverflow.com/questions/55396786/…
【解决方案2】:

如果您想检查两个模板模板类是否相同而不专门:

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>());

【讨论】:

    【解决方案3】:

    检查此post。它们提供了一种方法来检查某些东西是否是模板类的特化:

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

    【讨论】:

    • 如果类有两个模板参数,一个类型名和一个已知类型,会发生什么。例如template &lt;class T, bool Resize = true&gt; class vector;
    【解决方案4】:

    你可以,但需要一点 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,类...”,因为向量不采用 1 个模板参数,而是 2 个。在一般情况下,您不知道将使用多少个默认参数

    【讨论】:

      猜你喜欢
      • 2016-08-07
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 2021-03-06
      • 2012-10-02
      • 1970-01-01
      相关资源
      最近更新 更多