标准::initializer_list的实施
the implemention of std::initializer_list
我从头文件initializer_list
复制了代码,并将类名重命名为my_initializer_list
template<class _E>
class my_initializer_list
{
public:
typedef _E value_type;
typedef const _E& reference;
typedef const _E& const_reference;
typedef size_t size_type;
typedef const _E* iterator;
typedef const _E* const_iterator;
private:
iterator _M_array;
size_type _M_len;
// The compiler can call a private constructor.
constexpr my_initializer_list(const_iterator __a, size_type __l)
: _M_array(__a), _M_len(__l) { }
public:
constexpr my_initializer_list() noexcept
: _M_array(0), _M_len(0) { }
// Number of elements.
constexpr size_type
size() const noexcept { return _M_len; }
// First element.
constexpr const_iterator
begin() const noexcept { return _M_array; }
// One past the last element.
constexpr const_iterator
end() const noexcept { return begin() + size(); }
};
和代码:
int main()
{
my_initializer_list<int> foo = {1,2,3};
return 0;
}
并得到错误:
could not convert '{1, 2, 3}' from '<brace-enclosed initializer list>' to 'my_initializer_list<int>'
我的问题:STL如何实现initializer_list类?
它适用于std::initializer_list
,因为即使std::initializer_list
是一个类,它也不是一个常规类。这是一个非常非常特殊的类,从某种意义上说,当你编写auto x = {1,2,3};
编译器将推断x
std::initializer_list<int>
并相应地对其进行初始化。编译器在这里执行黑魔法来执行类型推断和初始化。它不仅是库功能。这也是一个核心语言功能。
如果你打算改用my_initializer_list
,那么它的构造函数需要接受std::initializer_list
,以便编译器可以为你做黑魔法。
请注意,{1,2,3}
是一个无类型的表达式 - 好吧,迂腐地说,它甚至不是一个表达式;只有在某些特殊情况下,它才可用于使用一些特殊规则初始化对象。例如,请参阅以下内容:
auto items = {1,2,3}; //OK: items is inferred to be std::initializer_list<int>
//must #include <initializer_list>
但是,对于模板,规则是不同的:
template<typename T>
void f(T const & items);
f({1,2,3}); //ILL-FORMED: T cannot be deduced to be
//std::initializer_list<int> or anything else
//even if you use #include <initializer_list>
f(std::initializer_list<int>{1,2,3}); //OK: #include <initializer_list>
f(std::vector<int>{1,2,3}); //OK: #include <vector>
//because std::vector accepts std::initializer_list<T>
希望有帮助。
相关文章:
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 铸造标准::有没有回到原来的类型
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 标准库类型的赋值运算符的引用限定符
- 标准是否严格定义了该程序应该如何编译?
- 如何从Windows应用程序输出到标准?
- 安全到标准:移动会员?
- 如何正确将字符串转换为标准::时间::system_clock::time_point?
- 这是否符合C++标准:双响双响,例如!!(-0.0).
- 标准::变体的赋值运算符
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- 如何在 Mac 上使用 c++17 并行标准库算法?
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 在C++标准中定义了对非限定 *mem-initializer-id* 的查找