gpt4 book ai didi

c++ - 如何在 `static_assert`成员初始化列表中构造一个模板类?

转载 作者:搜寻专家 更新时间:2023-10-31 01:25:59 24 4
gpt4 key购买 nike

我有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>的正确方法是什么? constutor 参数,在上述情况下?

最佳答案

你试图做的,一个 static 断言来检查构造函数的参数,(据我所知)是根本不可能的。

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

我能想象的最好的是一个 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 不是t)

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
}

关于c++ - 如何在 `static_assert`成员初始化列表中构造一个模板类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55996035/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com