编译时C++函数,检查是否所有模板参数类型都是唯一的

Compile-time C++ function to check whether all template argument types are unique(编译时C++函数,检查是否所有模板参数类型都是唯一的)
本文介绍了编译时C++函数,检查是否所有模板参数类型都是唯一的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个很好的问题(Which substitution failures are not allowed in requires clauses?)提出了下一个问题。

需要编写一个编译时函数template<typename... Ts> constexpr bool allTypesUnique(),如果所有参数类型都是唯一的,则返回true,否则返回false。限制是不成对比较参数类型。遗憾的是,答案只解释了为什么不能用某种特定的方法实现这种功能。

我认为解决方案可以使用多重继承来实现。其思想是使一个类继承自多个类:Ts中的每个类型对应一个类。每个这样的类都根据T定义一个带有签名的虚函数。如果在Ts中多次找到某个T,则子类中的函数f将覆盖基类中的函数,并且可以检测到:

template<typename> struct A{};

template<typename T, typename... Ts>
struct B : B<Ts...> {
    using B<Ts...>::f;
    constexpr virtual void f(A<T>, bool & unique) { if( ++count > 1 ) unique = false; }
    int count = 0;
};

template<typename T>
struct B<T> {
    constexpr virtual void f(A<T>, bool & unique) { if( ++count > 1 ) unique = false; }
    int count = 0;
};

template<typename... Ts>
constexpr bool allTypesUnique() {
    B<Ts...> b;
    bool res = true;
    ( b.f( A<Ts>{}, res ), ... );
    return res;
}

int main() {
    static_assert( allTypesUnique<void>() );
    static_assert( allTypesUnique<void, int&>() );
    static_assert( !allTypesUnique<int&, int&>() );
    static_assert( allTypesUnique<char, short, int>() );
    static_assert( !allTypesUnique<char, short, char>() );
}

演示:https://gcc.godbolt.org/z/8jhnE7P11

我很好奇,这个解决方案正确吗?这个问题有没有更简单的解决方案?

推荐答案

如果根据每个给定类型使用虚拟基类,则结果类中的每个唯一类型都将恰好有一个基类实例。如果给定类型的数量是生成的基类的数量,则每个类型都是唯一的。您可以通过其大小测量生成的基类的数量,但必须注意其中有一个大小取决于实现的vtable指针。因此,每个生成的类型都应该足够大,以隐藏对齐问题。

btw:它也适用于引用类型。


template < typename T> struct AnyT { char i[128]; };

template < typename FIRST, typename ... T>
struct CheckT: virtual AnyT<FIRST>, virtual CheckT<T...> { };

template < typename FIRST >
struct CheckT<FIRST>: virtual AnyT<FIRST> {};


template < typename ... T>
constexpr bool allTypesUnique()
{
    using T1 = CheckT<int>;
    using T2 = CheckT<bool, int>;

    constexpr std::size_t s1 = sizeof( T1 );
    constexpr std::size_t s2 = sizeof( T2 );
    constexpr std::size_t diff = s2 - s1; 
    constexpr std::size_t base = s1 - diff;
    constexpr std::size_t measure = sizeof( CheckT< T...> );

    return !((sizeof...(T)*diff+base) - measure);
}


int main() {
    static_assert( allTypesUnique<void>() );
    static_assert( allTypesUnique<void, int>() );
    static_assert( !allTypesUnique<void, void>() );
    static_assert( allTypesUnique<char, short, int>() );
    static_assert( !allTypesUnique<char, short, char>() );
}

Demo

这篇关于编译时C++函数,检查是否所有模板参数类型都是唯一的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Unknown type name __m256 - Intel intrinsics for AVX not recognized?(未知类型名称__M256-英特尔AVX内部功能无法识别?)
How can an declare an array in a function that returns an array in c++(如何在用C++返回数组的函数中声明数组)
Is it possible to define a class in 2 or more file in C++?(在C++中可以在两个或多个文件中定义一个类吗?)
Why can#39;t I create an array of automatic variables?(为什么我不能创建一个自动变量数组?)
zeromq: reset REQ/REP socket state(Zeromq:重置REQ/REP套接字状态)
Can I resize a vector that was moved from?(我可以调整从中移出的矢量的大小吗?)