提问人:Emile Papillon-Corbeil 提问时间:11/6/2023 最后编辑:Nicol BolasEmile Papillon-Corbeil 更新时间:11/6/2023 访问量:51
迭代器构造函数的推导模板参数
Deducting template parameter for iterator constructor
问:
我正在尝试为我的类创建一个构造函数,该构造函数将容器的迭代器作为参数并创建另一种类型的容器(假设类似于数组中的跨度)。
我想使用模板推导指南来支持这一点,并且我成功地使用了非 cv 合格的迭代器,但是当我通过常量迭代器时,它未能扣除:
// Deduction guide
<template typename Iterator>
Foo(Iterator begin, Iterator end) -> Foo<typename std::iterator_traits<Iterator>::value_type>;
std::vector<int> v{1, 2, 3, 4, 5};
Foo foo(v.begin(), v.end());
Foo otherFoo(v.cbegin(), v.cend()); // fails deduction
经过一些反复试验,我能够让它与这个推论指南一起工作:
template <class Iterator>
Foo(Iterator begin, Iterator end) -> Foo<std::conditional_t<std::is_const_v<typename std::iterator_traits<Iterator>::value_type>,
typename std::iterator_traits<Iterator>::value_type,
typename std::iterator_traits<Iterator>::value_type const>>;
但是当我使用 C++20 进行编译时,我不明白为什么会这样。从 cpp 首选项中,应剥离 cv-qualification。std::iterator_traits::value_type
作为测试,使用相同的环境,我进行了以下测试:
// test with non-const iterator
if (std::is_const_v<std::iterator_traits<decltype(v.begin())>::value_type>)
{
std::cout << "it is const" << std::endl;
} else
{
std::cout << "It is not const" << std::endl;
}
// test with const iterator
if (std::is_const_v<std::iterator_traits<decltype(v.cbegin())>::value_type>)
{
std::cout << "it is const" << std::endl;
} else
{
std::cout << "It is not const" << std::endl;
}
并得到了预期:两者都在打印“它不是常量”。那么,为什么上面的模板指南会起作用呢?
示例类
template <class T>
class Foo{
public:
template <class Iterator>
Foo(Iterator begin, Iterator end)
: mData(&*begin)
, mSize(std::distance(begin, end)) {}
T operator[](std::size_t i) {
return *(mData+i);
}
private:
T *mData;
std::size_t mSize;
};
// Template deduction guides
template <class Iterator>
Foo(Iterator begin, Iterator end) -> Foo<std::conditional_t<std::is_const_v<typename std::iterator_traits<Iterator>::value_type>,
typename std::iterator_traits<Iterator>::value_type,
typename std::iterator_traits<Iterator>::value_type const>>;
答:
0赞
康桓瑋
11/6/2023
#1
那么,为什么上面的模板指南会起作用呢?
由于始终是 cv-unqualified,因此这总是假的,因此您的约简指南等效于value_type
std::conditional_t
template <class Iterator>
Foo(Iterator begin, Iterator end) ->
Foo<typename std::iterator_traits<Iterator>::value_type const>;
这意味着实际上推导出 是 而不是 .Foo(v.begin(), v.end())
Foo<const int>
Foo<int>
C++20 中的适当定义是
template <class Iterator>
Foo(Iterator begin, Iterator end) ->
Foo<std::remove_reference_t<std::iter_reference_t<Iterator>>>;
评论
T = value_type const
conditional_t
begin()
cbegin()