首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解释cppreference.com中有关迭代器标记的示例代码

解释cppreference.com中有关迭代器标记的示例代码
EN

Stack Overflow用户
提问于 2015-06-03 08:51:29
回答 2查看 394关注 0票数 4

有谁能解释一下could网站的样本中的几个点吗?该技术描述了函数重载取决于迭代器类型。前两种类型与“使用”是明确的理解。这些问题涉及高级管理小组的职能:

  1. 在模板参数列表中-"typename =.“如果没有参数名,这是否意味着使用默认值而不能在函数调用中覆盖此值?
  2. 正确理解第二个模板参数的用法吗?只有在传递的迭代器类型和期望的迭代器标记的类型相等的情况下才会生成函数吗?
代码语言:javascript
复制
1. could you explain the using of third template parameter in second function alg and the comment there: 

"typename = void> // dummy值以避免模板重新定义错误“

代码在这里(tags):

代码语言:javascript
复制
template<typename Condition, typename T = void>
using EnableIf_t = typename std::enable_if<Condition::value, T>::type;

template<typename Iterator, typename IteratorTag>
using IsSameIteratorCond = 
    std::is_same<IteratorTag, 
    typename std::iterator_traits<Iterator>::iterator_category>;

template<
    typename BDIter, 
    typename = EnableIf_t<IsSameIteratorCond<BDIter, std::bidirectional_iterator_tag>>>
void alg(BDIter, BDIter)
{
    std::cout << "alg() called for bidirectional iterator\n";
}

template<
    typename RAIter, 
    typename = EnableIf_t<IsSameIteratorCond<RAIter, std::random_access_iterator_tag>>, 
    typename = void> // dummy value to avoid template re-definition error
void alg(RAIter, RAIter)
{
    std::cout << "alg() called for random-access iterator\n";
}

int main()
{
    std::vector<int> v;
    alg(v.begin(), v.end());

    std::list<int> l;
    alg(l.begin(), l.end());
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-03 09:05:48

  1. typename = ...声明一个未命名的模板参数。客户端代码仍然可以覆盖它,但是参数不能在函数定义中使用。之所以在这里使用它,是因为第二个模板参数用于利用SFINAE,而不是计算要在定义中使用的类型。
  2. 正确,如果迭代器类型与预期类型不同,则函数将从重载候选集中删除。
  3. 需要使用虚拟参数,因为默认值不是模板签名的一部分,因此两个版本的alg将尝试定义相同的函数模板。

使用默认值和虚拟参数对我来说很难看,我更喜欢使用标记分派:

代码语言:javascript
复制
template<typename BDIter>
void alg(BDIter, BDIter, std::bidirectional_iterator_tag)
{
    std::cout << "alg() called for bidirectional iterator\n";
}

template <typename RAIter>
void alg(RAIter, RAIter, std::random_access_iterator_tag)
{
    std::cout << "alg() called for random-access iterator\n";
}

template <typename It>
void alg(It a, It b)
{
    return alg(a, b, typename std::iterator_traits<It>::iterator_category{});
}
票数 4
EN

Stack Overflow用户

发布于 2015-06-03 09:03:32

  1. 不,用户可以覆盖参数。命名参数是可选的。如果你不想用的话你就不用这么做了。
  2. 是。对于要启动的第一个重载,标记必须等于std::bidirectional_iterator_tag,对于第二个重载,必须等于std::random_access_iterator_tag
  3. 如果没有第三个模板参数,两个函数声明将是相同的,这是非法的。它们要么按参数、返回类型、名称或模板参数不同(这里就是这样)。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30615190

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档