如何检查可变模板参数的唯一性?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (38)

我想要各种模板参数必须是唯一的。我知道当多重继承,相同的类继承是不允许的。

struct A{};
struct B: A, A{}; // error

使用这个规则,我做了一个小代码。

#include <type_traits>

template< class T> struct id{};
template< class ...T> struct base_all : id<T> ... {};

template< class ... T>
struct is_unique
{
     template< class ... U>
 static constexpr bool test( base_all<U...> * ) noexcept { return true; }

template< class ... U>
static constexpr bool test( ... ) noexcept { return false;}


static constexpr bool value = test<T...>(0);
};

int main()
{
    constexpr bool b = is_unique<int, float, double>::value; // false -- Why?
    constexpr bool c = is_unique< int, char, int>::value; // false

   static_assert( b == true && c == false , "!");// failed.
}

但我的计划并没有像我预期的那样有效。怎么了?

//     #include <type_traits>
//     #include <cstddef>
//    
//     template< class ... U> struct pack{};
//    
//     template< class T> struct id{};
//     template< class T> struct base_all;
//     template< class ... T> struct base_all< pack<T...> > : id<T>  ... {};
//        
//     
//    
//     template< class ... T>
//     struct is_unique
//     {
//           template< class P,  std::size_t  =  sizeof(base_all<P>) >
//          struct check;
//     
//       template< class ...U>
//      static constexpr bool test(check< pack<U...> > * ) noexcept { return true;}
//        
//        template< class ... U>
//        static constexpr bool test(...)noexcept { return false;}
//        
//        static constexpr bool value =  test<T...>(0);
//        };
//        
//        int main()
//        {
//            constexpr bool b = is_unique<int, float, double>::value; // true
//            constexpr bool c = is_unique< int, char, int>::value; // false
//             
//          static_assert( b == true && c == false , "!");// success.
//        }
//
#include <cstddef>
#include <iostream>
#include <type_traits>

namespace mpl
{

template< class T > using invoke = typename T :: type ;

template< class C, class I, class E > using if_t     = invoke< std::conditional< C{}, I, E> >;

template< class T > struct id{};
struct empty{};

template< class A, class B > struct base : A, B {};

template< class B , class ... > struct is_unique_impl;

template< class B > struct is_unique_impl<B>: std::true_type{};

template< class B, class T, class ... U>
struct is_unique_impl<B, T, U...> : if_t< std::is_base_of< id<T>, B>, std::false_type, is_unique_impl< base<B,id<T>>, U...> >{};


template< class ...T >struct is_unique : is_unique_impl< empty, T ... > {};



} // mpl    

int main()
{
    constexpr bool b = mpl::is_unique<int, float, double>::value;

    constexpr bool c = mpl::is_unique< int, char, int > :: value;

    static_assert( b == true   , "!");
    static_assert( c == false, "!");

    return 0;

}
提问于
用户回答回答于

另一个O(Logn)实例化深度解。它仍然需要一个主要的清理,注释,命名空间,重命名,和减少代码重复。

O(Logn)实例化深度版本gen_seq依赖于。

#include <cstddef>

    // using aliases for cleaner syntax
    template<class T> using Invoke = typename T::type;

    template<std::size_t...> struct seq{ using type = seq; };

    template<class S1, class S2> struct concat;

    template<std::size_t... I1, std::size_t... I2>
    struct concat<seq<I1...>, seq<I2...>>
      : seq<I1..., (sizeof...(I1)+I2)...>{};

    template<class S1, class S2>
    using Concat = Invoke<concat<S1, S2>>;

    template<std::size_t N> struct gen_seq;
    template<std::size_t N> using GenSeq = Invoke<gen_seq<N>>;

    template<std::size_t N>
    struct gen_seq : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{};

    template<> struct gen_seq<0> : seq<>{};
    template<> struct gen_seq<1> : seq<0>{};

除了索引序列生成之外,该解决方案甚至应该具有O(1)实例化深度。它使用的不是多重继承,而是使用std::array<std::false_type, size>通过SFINAE进行O(1)-实例化-深度或。

执行is_one_of请注意,“是其中之一”是与“是唯一的”相反的概念。

#include <array>

// check if `T` is in `Us...`
template<class T, class... Us>
struct is_one_of
{
    template<class T1>
    static constexpr auto SFINAE(int)
    -> decltype( std::array<std::false_type, sizeof...(Us)>
                 {{std::is_same<T1, Us>{}...}} )
    {  return {}; /* only to suppress warning */  }

    template<class...>
    static constexpr int SFINAE(...) { return 42; }

    template<class T1>
    static constexpr bool test()
    {
        return std::is_same<decltype(SFINAE<T1>(0)), int>{};
    }

    static constexpr bool value = test<T>();
    constexpr operator bool() const { return value; }
};

执行are_unique:

namespace detail
{
    // `Any` type with a generic no-constraint ctor
    // to discard a number of arguments for a function template
    template<std::size_t>
    struct Any
    {
        template<class T>
        constexpr Any(T&&) {}
    };

    // `wrapper` is used as a substitute for `declval`,
    // and can keep track if `T` is a reference
    template<class T>
    struct wrapper { using type = T; };

    template<std::size_t I, class T, class... Us>
    struct is_one_of_pack
    {
        template<std::size_t... I1s>
        struct helper
        {
            template<class... Remaining>
            static constexpr bool deduce_remaining(Any<I1s>..., Remaining...)
            {
                // unique <-> is one of
                return not is_one_of<T, typename Remaining::type...>{};
            }
        };

        template<std::size_t... I1s>
        static constexpr bool deduce_seq(seq<I1s...>)
        {
            return helper<I1s...>::template deduce_remaining(wrapper<Us>()...);
        }

        static constexpr bool create_seq()
        {
            return deduce_seq(gen_seq<I+1>{});
        }

        using type = std::integral_constant<bool, create_seq()>;
    };

    template<class... Packs>
    constexpr auto SFINAE(int)
    -> decltype( std::array<std::true_type, sizeof...(Packs)>
                 {{typename Packs::type{}...}} )
    {  return {}; /* only to suppress warning */  }

    template<class...>
    static constexpr int SFINAE(...) { return 42; }

    template<class... Packs>
    constexpr bool test()
    {
        return std::is_same<decltype(SFINAE<Packs...>(0)), int>{};
    }

    template<class... Ts, std::size_t... Is>
    constexpr bool deduce_seq(seq<Is...>)
    {
        return test< is_one_of_pack<Is, Ts, Ts...>... >();
    }
}

template<class... Ts>
struct are_unique
: std::integral_constant<bool,
                         detail::deduce_seq<Ts...>(gen_seq<sizeof...(Ts)>{})>
{};

用法示例:

#include <iostream>
#include <iomanip>
int main()
{
    bool a = are_unique<bool, char, int>();
    bool b = are_unique<bool, char, int, bool>();
    bool c = are_unique<bool, char, bool, int>();
    std::cout << std::boolalpha;
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
}

热门问答

对象存储COS有没有日志功能?

Hyman Wang

腾讯云 · 高级产品经理 (已认证)

推荐已采纳

你的cos 是否开通了 CDN 加速,如果开通了CDN 加速,可以去 CDN 的控制台下: (统计分析 --- 监控 )页面下拉到底部,可以通过 URL 查看流量情况。

对象存储里的视频能在线播放么?

Jinqn

腾讯 · 高级工程师 (已认证)

腾讯云COS前端开发
推荐

购买的云数据库里面有什么类型的数据库?有SQLserver吗?可以自己安装SQLserver吗?

帅的惊动我国计算机大神
推荐已采纳
云关系型数据库让您在云中轻松部署、管理和扩展的关系型数据库,提供安全可靠、伸缩灵活的按需云数据库服务。腾讯云关系型数据库提供 MySQL、SQL Server、MariaDB、PostgreSQL 数据库引擎,并针对数据库引擎的性能进行了优化。云关系型数据库是一种高度可用的托管服...... 展开详请

linux如何限制单一ip对服务器的日访问量?

小爱同学

腾讯云 · 技术支持 (已认证)

推荐
您根据当前网站规模和业务了解下【网站管家 WAF】,企业站点可有效抵御恶意攻击,垃圾访问。 图片.png 您反馈网站短信验证码被盗刷,也可结合自己业务,可自行部署iptables进行手动拦截。或其他方式 例如您的网站是nginx,在web配置文件中开启配置HttpLimitR...... 展开详请

兼容性测试只能上传apk测试的吗?

WeTest质量开放平台团队专注游戏,提升品质
推荐

目前不支持公众号的兼容测试,还请知晓

关于群自动解散的问题?

安稳

腾讯科技 · 工单技术支持 (已认证)

推荐
您好,临时群是没有的。云通信的群组只有私有群(Private)、公开群(Public)、聊天室(ChatRoom)、音视频聊天室(AVChatRoom)和在线成员广播大群(BChatRoom)这五种。 您说的这个需求,思路:创建群组时,服务端记录一下时间,到达约定解散的时间以后,...... 展开详请

所属标签

扫码关注云+社区