如何将括号括起来的初始化器列表传递给函数?

问题描述

我想编写一个可以与参数一起使用的函数,否则该参数可能直接出现在基于范围的循环中:

template <typename Iterable>
void sayIt(const Iterable& stuff) {
    for (const auto& e : stuff) {
        cout << e << endl;
    }
}

这对于stl容器和其他类型可以正常使用,但不适用于括号括起来的初始化程序:

std::vector<std::string> baz(2,"sorry");
sayIt(baz);              // okay
sayIt({"foo","bar"});   // not okay

有没有一种方法可以使该功能与两者同时使用?

解决方法

Braced-init-list没有类型,并且导致template argument deduction失败。

非推断上下文

在以下情况下,用于构成P的类型,模板和非类型值不参与模板自变量的推导,而是使用在其他地方推导或明确指定的模板自变量。如果仅在非推导上下文中使用模板参数并且未明确指定模板参数,则模板参数推导将失败。

  1. 参数P,其A是一个大括号初始化列表,但P不是std::initializer_list,对一个参数的引用(可能是cv限定的)或对数组的引用:

您可以将模板参数明确指定为std::initializer_list来绕开推论,

sayIt<std::initializer_list<std::string>>({"foo","bar"});

或添加另一个重载std::initializer_list

template <typename T>
void sayIt(std::initializer_list<T> stuff) {
    sayIt<decltype(stuff)>(stuff);
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...