c++ - 作为容器的初始化程序列表不起作用

标签 c++ templates c++11

考虑以下示例:

#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;
}

它与带有 initializer_list 的第二个 isElementOf 模板编译得很好。尽管如此,内容或多或少与第一个模板相同。它使用 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 兼容的类。为什么容器模板不适用于初始化列表?有没有办法只用一个模板解决问题?

Live example

最佳答案

A function parameter for which the associated argument is an initializer list (8.5.4) but the parameter does not have std::initializer_list or reference to possibly cv-qualified std::initializer_list type

是非推导上下文 (§14.8.2.5 [temp.deduct.type]/p5),因此编译器无法推导 Containerbraced-init-list 本身没有类型。

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

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) );
}

请注意,您不应使用 initializer_list 默认参数,除非您确定代码不会受到其复制语义的影响 - 底层数组的生命周期不受任何影响initializer_list 对象的复制。

关于c++ - 作为容器的初始化程序列表不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25738069/

相关文章:

C++ std::move 指针

c++11 - 如何避免模板实例化和符号表导致的C++代码膨胀?

C++模板实例化,错误: member of non-class type 'int'

c++ - std::function.target 返回 null

C++11 参数包重载

c++ - CUSP 稀疏库给出奇怪的结果

c++ - 在模板中使用 'export' 关键字时解决此错误?

c++ - 整数的快速排序算法

c++ - 获取 C++ 函数参数的类型

c++ - C2977 : 'std::tuple' : too many template arguments (MSVC11)