【问题标题】:SFINAE applied to iteratorSFINAE 应用于迭代器
【发布时间】:2018-04-25 10:03:37
【问题描述】:

我正在编写一个模板函数,它应该只接受包含特定类型(由 template 定义)的任何容器的随机访问迭代器。 目前,我首先尝试使用 SFINAE 限制迭代器的类型,但代码无法编译。

#include <iostream>
#include <type_traits>
#include <vector>

template<typename It,
         std::enable_if<
             std::is_same<typename std::iterator_traits<It>::iterator_category,
                          std::random_access_iterator_tag>::value,
             typename std::iterator_traits<It>::difference_type>>
void func(const It& begin, const It& end)
{
    std::cout << begin[0] << std::endl;
}


int main()
{
    std::vector<int> a = {0,1,2,3,4,5};
    func(a.begin(), a.end());
    return 0;
}

错误是:

error: ‘struct std::enable_if<std::is_same<typename
std::iterator_traits<_Iter>::iterator_category,std::random_access_iterator_tag::value,
typename std::iterator_traits<_Iterator>::difference_type>’ is not a
valid type for a template non-type parameter template<typename It,
std::enable_if<std::is_same<typename std::iterator_traits

error: no matching function for call to
‘func(std::vector<int>::iterator, std::vector<int>::iterator)’
func(a.begin(), a.end());

【问题讨论】:

  • 仅供参考,您编写的 template&lt;typename T, Z&lt;...&gt;&gt; 等价物无法编译,因为 Z&lt;...&gt; 不是非类型模板参数的有效类型

标签: c++ stl iterator sfinae


【解决方案1】:

我无法解析您的enable_if。 这行得通:

template<typename It, typename std::enable_if<std::is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0>
void func(const It& begin, const It& end)
{
    std::cout << begin[0] << std::endl;
}


int main()
{
    std::vector<int> a = {0,1,2,3,4,5};
    func(a.begin(), a.end());
    return 0;
}

但可能是我误解了你的意图。

【讨论】:

  • 谢谢。我如何编辑您的答案以确保迭代器仅在 std::string 的容器上?
  • 您可以在 enable if 的条件下使用 && 并添加其他条件来检查 std::iterator_traits::value_type (已删除 const volatile)是否为 std::string跨度>
【解决方案2】:

您需要typename = 才能像这样为 SFINAE 使用匿名类型:

template<typename It,
         typename = std::enable_if<std::is_same<typename std::iterator_traits<It>::iterator_category,
                                                std::random_access_iterator_tag>::value,
                                   typename std::iterator_traits<It>::difference_type>>
void func(const It& begin, const It& end)
{
    std::cout << begin[0] << std::endl;
}

或者,您可以使用 std::enable_if&lt;...&gt;::type 作为函数的返回类型。

如果您正在使用 C++17 或更高版本,请考虑查看正在进入 C++20 的概念提案。

【讨论】:

  • 谢谢。如果我还想检查容器中元素的类型,我该如何编辑您的答案?
  • 这听起来像是一个新问题——如果你问这个问题,请记住具体说明你需要对类型进行什么样的约束。哦,我们鼓励您对任何对您有帮助的答案进行投票。
  • 当您为另一个迭代器类型重载 func 时,您的 sfinae 将被破坏。见stackoverflow.com/q/40250368/4832499。另一方面,将其放入返回类型中会起作用。
  • @PasserBy - 不,没关系(不同的It)。但是您的链接问题当然值得一读,以更好地了解什么有效,什么无效。
猜你喜欢
  • 2012-08-23
  • 2013-01-16
  • 2014-10-29
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 1970-01-01
  • 2010-12-19
  • 1970-01-01
相关资源
最近更新 更多