gpt4 book ai didi

C++:SFINAE 区分填充和范围构造函数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:17:33 26 4
gpt4 key购买 nike

Here是一个询问如何区分填充和范围构造函数的问题。代码复制在这里:

template <typename T>
struct NaiveVector {
vector<T> v;
NaiveVector(size_t num, const T &val) : v(num, val) { // fill
cout << "(int num, const T &val)" << endl;
}

template <typename InputIterator>
NaiveVector(InputIterator first, InputIterator last) : v(first, last) { // range
cout << "(InputIterator first, InputIterator last)" << endl;
}
};

如该问题中所述,上面的代码不起作用。解决方案是使用 SFINAE 定义范围构造函数,像这样 example :

template
<
typename InputIterator
, typename = typename ::std::enable_if
<
::std::is_same
<
T &
, typename ::std::remove_const
<
decltype(*(::std::declval< InputIterator >()))
>::type
>::value
, void
>::type
>
NaiveVector(InputIterator first, InputIterator last) : v(first, last)
{
cout << "(InputIterator first, InputIterator last)" << endl;
}

此解决方案的要点是比较 InputIterator 的取消引用类型与 T & .如果它确实是指向 T 的迭代器, std::is_same 的比较将为真,并且将选择范围构造函数;如果不是迭代器,则会出现模板替换失败,因此将删除范围构造函数,从而选择填充构造函数。

但是,上述解决方案存在问题。如果输入InputIterator属于 const_iterator输入(例如 cbegin() ),然后取消引用它会产生一个 const T & , 及其 const -ness 无法通过 std::remove_const 删除(解释了 here ),所以 std::is_same 中的比较将为 false,导致范围构造函数被错误删除。

GNU's C++ STL had a bug possibly (I guess) because of this. In this bug, the method only accepts an iterator, but not a const_iterator.

问题:

(1) 是否有比组合两个 std::is_same更好的解决方法?使用 OR 运算符的条件,将取消引用的类型与 T & 进行比较, 另一个是 const T &

(2) 如果采用 (1) 中描述的解决方法,则为 std::remove_const仍然有必要,现在它无法删除 const -ness 来自引用类型,并且取消引用(const 或非 const)迭代器将始终产生引用,const T &T & .

最佳答案

示例代码确实是错误的,因为它不支持const_iterator , std::decay会更合适:

template
<
typename InputIterator
, typename = typename ::std::enable_if
<
::std::is_same
<
T
, typename ::std::decay
<
decltype(*(::std::declval< InputIterator >()))
>::type
>::value
, void
>::type
>
NaiveVector(InputIterator first, InputIterator last);

或更简单 std::iterator_traits<InputIterator>::value_type .

但更好的是,IMO 将是 std::is_constructible .当迭代器返回包装器时处理(可能是 std::vector<bool> )

template <typename InputIterator,
typename ::std::enable_if<
::std::is_constructible<
T,
decltype(*::std::declval<InputIterator>())
>::value
>::type* = nullptr
>
NaiveVector(InputIterator first, InputIterator last);

Demo

关于C++:SFINAE 区分填充和范围构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45889587/

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