繁体   English   中英

如何在成员初始值设定项列表中“ static_assert”构建模板类?

[英]How to `static_assert` the construction of a template class in member initializer list?

我有MyClass这是一个模板类。 我想提供一个初始化r列表构造函数,以便可以方便地编写:

MyClass<int> Arr0{ 1,  2,  3, 4, 5, 8 };

另一方面, 我不想在此列表中有重复项 ,因为此类意味着仅具有唯一的用户输入。 我已经看到了许多方法来检查数组中的重复项,并且我想出了has_duplicates()以下函数。

我试图结合检查以下想法: std::initializer_list<T> ed临时元素(或数组)是否在成员初始化器列表本身中包含任何重复的元素; 如果它包含static_assert()模板实例化,则将不会构造此类的对象。

以下是我的代码的最小示例。

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>
#include <initializer_list>

template <typename Iterator> // function to check duplicates(which works fine)
constexpr bool has_duplicates(Iterator start, Iterator end)
{
    if (start == end) return false;
    using Type = typename std::remove_reference_t<decltype(*end)>;
    std::map<Type, std::size_t> countMap;
    for (; start != end; ++start)
    {
        countMap[*start]++;
        if (countMap[*start] >= 2) return true;
    }
    return false;
}

template <typename T> class MyClass
{
private:
    std::vector<T> m_vec;

public:
    MyClass(std::initializer_list<T> a)
        : (has_duplicates(a.begin(), a.end()) //-----> here is the problem
            ? static_assert(false, " the array has duplicates....")
            : m_vec(a)
           )
    {
        std::cout << "Constriction successful....";
    }
};

int main()
{
    std::vector<int> test{ 1, 2, 3, 4, 1 };
    std::cout << std::boolalpha 
        << has_duplicates(test.begin(), test.end()) << std::endl; // works
    MyClass<int> Arr0{ 1,  2,  3, 4 }; // error
    return 0;
}

在MSVC 16.0(C ++ 17标志)中进行编译时,这给了我错误:

error C2059: syntax error: 'static_assert'
note: while compiling class template member function 'MyClass<int>::MyClass(std::initializer_list<_Ty>)'
      with
      [
          _Ty=int
      ]
note: see reference to function template instantiation 'MyClass<int>::MyClass(std::initializer_list<_Ty>)' being compiled
      with
      [
          _Ty=int
      ]
note: see reference to class template instantiation 'MyClass<int>' being compiled
error C2143: syntax error: missing ';' before '}'
error C2059: syntax error: ')'
error C2447: '{': missing function header (old-style formal list?)

它说了一个简单的语法错误,但按照static_assert ,我看不到任何错误

有人可以帮我找出错误吗?

在上述情况下,防止构造std::initializer_list<T>构造函数参数的正确方法是什么?

您正在尝试做的事情(一个静态的断言来检查构造函数的参数)(据我所知)是根本不可能的。

static_assert()在编译时(其中MyClass对象已初始化(可以初始化)运行时static_assert()起作用。

我能想象的最好的是make_MyClass()函数,该函数接收作为模板参数的参数列表

template <auto v0, auto ... vs>
auto make_MyClass ()
 {
   static_assert( false == has_duplicates<v0, vs...>() );

   return MyClass<decltype(v0)>{ v0, vs... };
 }

因此您可以执行static_assert()因为现在您知道了编译时的值; 我已经如下重写has_duplicates()函数,因为您的原始函数无法有效地进行constexpr (因为std::map不是)

template <typename = void>
constexpr bool has_duplicates ()
 { return false; }

template <auto v0, auto ... vs>
constexpr bool has_duplicates ()
 { return ((v0 == vs) || ... ) || has_duplicates<vs...>(); }

以下是完整的编译示例

#include <iostream>
#include <vector>
#include <initializer_list>

template <typename = void>
constexpr bool has_duplicates ()
 { return false; }


template <auto v0, auto ... vs>
constexpr bool has_duplicates ()
 { return ((v0 == vs) || ... ) || has_duplicates<vs...>(); }  

template <typename T> class MyClass
{
private:
    std::vector<T> m_vec;

public:
    MyClass(std::initializer_list<T> a) : m_vec{a}
     { std::cout << "Constriction successful...."; }
};

template <auto v0, auto ... vs>
auto make_MyClass ()
 {
   static_assert( false == has_duplicates<v0, vs...>() );

   return MyClass<decltype(v0)>{ v0, vs... };
 }

int main ()
 {
    std::cout << std::boolalpha 
        << has_duplicates<1, 2, 3, 4, 1>() << std::endl;

    auto mc0 = make_MyClass<1, 2, 3, 4, 5>(); // compile
    //auto mc1 = make_MyClass<1, 2, 3, 4, 1>(); // static_assert error
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM