当前位置: 首页 > 知识库问答 >
问题:

作为容器的初始值设定项列表不起作用

印瑾瑜
2023-03-14

考虑以下示例:

#include <algorithm>
#include <iterator>
#include <vector>

template<class InputIterator, class T>
bool privIsElementOf(const T& element, InputIterator first, InputIterator last)
{
  return ( std::find(first, last, element) != last );
}

template<class Container, class T>
bool isElementOf(const T& element, const Container & cont)
{
  return privIsElementOf( element, std::begin(cont), std::end(cont) );
}

template<class T>
bool isElementOf(const T& element, const std::initializer_list<T> iList)
{
  return privIsElementOf( element, std::begin(iList), std::end(iList));
}


int main()
{
  std::vector<int> myVec { 1 , 3 , 5};

  bool isElement  = isElementOf(3, myVec);
  bool isElement2 = isElementOf(3, {1 , 3, 5 });

  return 0;
}

它使用第二个isElementOf模板和initializer_list进行编译。然而内容或多或少与第一个模板相同。它使用std::begin和std::end。

当我删除第二个模板时,它显示以下编译错误:


    initList.cpp: In function ‘int main()’:
    initList.cpp:31:47: error: no matching function for call to ‘isElementOf(int, )’
       bool isElement2 = isElementOf(3, {1 , 3, 5 });
                                                   ^
    initList.cpp:31:47: note: candidate is:
    initList.cpp:12:6: note: template bool isElementOf(const T&, const Container&)
     bool isElementOf(const T& element, const Container & cont)
          ^
    initList.cpp:12:6: note:   template argument deduction/substitution failed:
    initList.cpp:31:47: note:   couldn't deduce template parameter ‘Container’
       bool isElement2 = isElementOf(3, {1 , 3, 5 });
                                                   ^

谁能给我解释一下这个问题吗?该模板只是要求提供与std::begin和std::end兼容的类。为什么容器模板不适用于初始化器列表?有没有办法只用一个模板来解决这个问题?

现场示例

共有1个答案

龚远
2023-03-14

一种函数参数,其关联参数是初始值设定项列表(8.5.4),但该参数没有标准的初始值设定项列表,也没有对可能符合cv条件的标准的初始值设定项列表的引用

是非推断上下文(§14.8.2.5[临时推断类型]/p5),因此编译器无法推断容器。带大括号的init列表本身没有类型。

一种可能性是提供默认模板参数来涵盖这种情况:

template<class T, class Container = std::initializer_list<T>>
bool isElementOf(const T& element, const Container & cont)
{
  return privIsElementOf( element, std::begin(cont), std::end(cont) );
}

请注意,除非您确信代码不会受其复制语义的影响,否则不应使用默认参数-基础数组的生存期不受对初始值设定项列表对象的任何复制的影响。

 类似资料:
  • 我有以下django-filter(https://github.com/alex/django-filter/)过滤器: 状态包含以下元组列表: 有人知道该如何处理吗?我使用的是最新(来自github)版本的django-filter。 TIA

  • 在前面的代码段中,除最后一个表达式外,所有表达式都已编译并正常运行。虽然最后一条语句看起来与其立即语句类似,但编译器会发出编译时错误—表达式的非法开始—而不是语句。为什么?

  • 我有以下代码: 我希望输出是:“base constructor,test:50”,但事实并非如此,因为构造函数是在初始化之前调用的,没有错误或警告,它只是编译。 有什么方法可以让构造函数在之后被调用吗?或者这是总体上的糟糕设计? 我正在尝试将所有的init方法和它们的调用放入构造函数insted中,这个行为阻止了我这样做。

  • 我相信现代C初始值设定项列表对于初始化对象非常有用,甚至不需要定义自己的构造函数: 但是,当我的类从另一个类继承时,这不起作用: 我尝试添加

  • 我已经创建了一个有2个INIT容器的作业荚,我的作业成功完成,但没有INIT容器的迹象 对我来说,作业应该在开始之前等待2个init容器的完成 操作系统为Red Hat Enterprise Linux Server 7.3(Maipo) 提前感谢您的帮助。

  • 我一直避免像下面这样的初始化 因为引用和指针限定符不适用于初始化。假设这是初学者学习的第一件事,与之相关的模糊性让我觉得下面的内容更清晰,也更不需要读者思考 有了C17和结构化绑定,我很开心,看到了很多潜力。C17禁止了C14和C11未能修复的东西,是一个而不是