C++ 检查两种类型是否属于同一模板

C++ 检查两种类型是否属于同一模板,c++,sfinae,typetraits,C++,Sfinae,Typetraits,我想检查两种类型的模板是否相同。作为一个例子,我希望下面的代码片段返回true,因为这两个对象都是向量,尽管内部元素的类型不同 在编译时进行检查很重要(这就是为什么函数是constexpr) #包括 #包括 #包括 模板constexpr bool CheckTypes(容器1 c1、容器2 c2) { 返回std::is_same::value; } int main() { 标准:向量v1(100,0); 标准:向量v2(100,0); std::cout检查这一点。它们提供了一种检查某个内

我想检查两种类型的模板是否相同。作为一个例子,我希望下面的代码片段返回
true
,因为这两个对象都是向量,尽管内部元素的类型不同

在编译时进行检查很重要(这就是为什么函数是constexpr)

#包括
#包括
#包括
模板constexpr bool CheckTypes(容器1 c1、容器2 c2)
{
返回std::is_same::value;
}
int main()
{
标准:向量v1(100,0);
标准:向量v2(100,0);
std::cout检查这一点。它们提供了一种检查某个内容是否是模板类的专用化的方法:

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

模板
结构是_专门化:std::false_类型{};
模板
结构是_专门化:std::true_类型{};
可能会这样做以保持原始界面:

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

模板
constexpr布尔检查类型(容器1 c1、容器2 c2){
返回值为_specialization::value&&is _specialization::value;
}
所以你可以这样做:

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

intmain(){
标准:向量v1(100,0);
标准:向量v2(100,0);
标准::cout给你:

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;
}
即使
T1
T2
不同(模板参数类型),
是相同的\u模板
是真实类型:

are_same_template<T<T1>, T<T2>> : std::true_type
模板是否相同:std::true\u类型


关于
template
而不是
template
:这是为了适应
std:
容器具有隐式模板参数的事实。感谢ConstantinosGlynos让我意识到了这一点。

您可以,但需要一点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;
}
#包括
#包括
#包括
#包括
模板
结构检查类型\u impl
{
constexpr静态布尔检查(Container1,Container2){返回false;}
};
模板<
模板类容器1,类…args1,类…args2>

struct CheckTypes\u implic如果您需要在编译时检查某些内容,您应该使用静态类型而不是变量进行操作。但是它们不是同一类型……容器是相同的,而不是实例化的类型。您可以使用
sizeof
进行检查,但我不确定解决方案的优雅程度。我希望它能够与任何容器。你为什么要检查这个?@Sombrero对dup不太满意。这个Q有点不同。OP给出了
std::vector
作为示例,但他们的问题更一般:“我想检查两种类型是否属于同一模板”。我喜欢这种方法,但为什么它在这里不起作用:我用g++、vc++和clang尝试过。所有这些方法都返回相同的结果。唯一的区别是c++17标志。Godbolt也返回0。我有一种感觉,
Coliru
出现了可怕的问题。在多个编译器和平台上进行了尝试(
rextester、ideone、Qt
godbolt
)。都给出相同的结果(
false
)即使启用了
c++17
标志。我认为
Coliru
编译器出现了问题……我不这么认为……因为这意味着
g++
vc++
都有相同的错误。Coliru也在使用
g++
。另外,我在想,
std::vector
容器有第二个模板参数用于
std::allocator
。部分专门化不包括使我认为它不是所选的参数。Sweeet(我是对的):@YSC您的答案很好,这是公认的答案。您现在能帮我找到一个稍有不同的答案吗?如果类有两个模板参数,一个是typename,另一个是已知类型,会发生什么情况。例如
模板类向量;
are_same_template<T<T1>, T<T2>> : std::true_type
#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;
}