大括号初始化列表推导指南
Deduction guide for brace initializer list
有一个与 std::initializer_list
非常相似的实现,用于标准 C++ 库不可用的环境:
template<typename T>
class initializer_list {
public:
using value_type = T;
using reference = const T &;
using const_reference = const T &;
using size_type = size_t;
using iterator = const T *;
using const_iterator = const T *;
private:
iterator m_array;
size_type m_length;
constexpr initializer_list( const_iterator array, size_type length ) noexcept : m_array( array ), m_length( length ) {}
public:
constexpr initializer_list( void ) noexcept : m_array( nullptr ), m_length( 0 ) {}
/* Number of elements */
constexpr size_type size( void ) const noexcept {
return m_length;
}
/* First element */
constexpr const_iterator begin( void ) const noexcept {
return m_array;
}
/* One past the last element */
constexpr const_iterator end( void ) const noexcept {
return begin() + size();
}
};
template<typename T>
constexpr const T * begin( initializer_list<T> list ) noexcept {
return list.begin();
}
template<typename T>
constexpr const T * end( initializer_list<T> list ) noexcept {
return list.end();
}
那么这样的initializer_list<T>
将要在另一个class构造函数中使用:
template<typename T>
struct user {
user( initializer_list<T> init_values ) { ... }
};
以及将两者结合使用的意图:
user<int> sample { 1, 2, 3, 4, 5 };
显然,编译器不知道如何推断大括号初始值设定项列表的类型,因此它使用上面实现的 initializer_list。我想应该实施某种推导指南来连接我的 initializer_list 实施和大括号初始化列表。但是我不知道如何实现。
有人可以告诉我如何实施所描述的推导指南吗?
in an environment where standart C++ library is not available
没有这样的事情。虽然独立的 C++ 实现可以自由地只实现标准库的一部分,但是 所有 有效的 C++ 实现必须提供一些组件。 std::initializer_list
属于这些组成部分。
因此,如果您拥有有效的 C++11 或更高版本的 C++ 实现,那么您必须拥有 <initializer_list>
header 及其内容。这不是可选的。如果您的实施没有提供,那么它就是有缺陷的。
它不是可选的原因是 std::initializer_list
的重要功能(即它从 braced-init-list 生成)是 C++ 语言,不是图书馆的。也就是说,编译器外部的代码 不可能 使 {}
语法结构成为与 std::initializer_list
行为方式完全相似的类型。
考虑您的代码:
user<int> sample { 1, 2, 3, 4, 5 };
如果你仔细想想,这应该意味着 user<int>
的构造函数将被调用,它有 5 个参数。毕竟,如果 user
有一个包含 5 个整数参数的构造函数,那就是这个意思。但这不是您想要的意思,对于 vector<int>
也不是那个意思。为什么?
因为 C++ 的语言有一个关于列表初始化的特殊规则,它检测是否存在一个构造函数,该构造函数采用匹配 braced-init-list 类型的 std::initializer_list
,然后创建一个 std::initializer_list
来传递给这个构造函数。此规则关闭了采用 std::initializer_list
且 没有其他类型 .
的构造函数的存在
您的代码不起作用,不是因为缺少推导指南,而是因为您的 initializer_list
类型在语言方面没有特殊规则。
您无法使用 user-defined 类型重新创建此语言行为。正如你不能使 typeid
return 成为 std::type_info
以外的类型。正如您不能使 enum class byte: unsigned char{};
具有与 std::byte
.
相同的行为一样
有一个与 std::initializer_list
非常相似的实现,用于标准 C++ 库不可用的环境:
template<typename T>
class initializer_list {
public:
using value_type = T;
using reference = const T &;
using const_reference = const T &;
using size_type = size_t;
using iterator = const T *;
using const_iterator = const T *;
private:
iterator m_array;
size_type m_length;
constexpr initializer_list( const_iterator array, size_type length ) noexcept : m_array( array ), m_length( length ) {}
public:
constexpr initializer_list( void ) noexcept : m_array( nullptr ), m_length( 0 ) {}
/* Number of elements */
constexpr size_type size( void ) const noexcept {
return m_length;
}
/* First element */
constexpr const_iterator begin( void ) const noexcept {
return m_array;
}
/* One past the last element */
constexpr const_iterator end( void ) const noexcept {
return begin() + size();
}
};
template<typename T>
constexpr const T * begin( initializer_list<T> list ) noexcept {
return list.begin();
}
template<typename T>
constexpr const T * end( initializer_list<T> list ) noexcept {
return list.end();
}
那么这样的initializer_list<T>
将要在另一个class构造函数中使用:
template<typename T>
struct user {
user( initializer_list<T> init_values ) { ... }
};
以及将两者结合使用的意图:
user<int> sample { 1, 2, 3, 4, 5 };
显然,编译器不知道如何推断大括号初始值设定项列表的类型,因此它使用上面实现的 initializer_list。我想应该实施某种推导指南来连接我的 initializer_list 实施和大括号初始化列表。但是我不知道如何实现。
有人可以告诉我如何实施所描述的推导指南吗?
in an environment where standart C++ library is not available
没有这样的事情。虽然独立的 C++ 实现可以自由地只实现标准库的一部分,但是 所有 有效的 C++ 实现必须提供一些组件。 std::initializer_list
属于这些组成部分。
因此,如果您拥有有效的 C++11 或更高版本的 C++ 实现,那么您必须拥有 <initializer_list>
header 及其内容。这不是可选的。如果您的实施没有提供,那么它就是有缺陷的。
它不是可选的原因是 std::initializer_list
的重要功能(即它从 braced-init-list 生成)是 C++ 语言,不是图书馆的。也就是说,编译器外部的代码 不可能 使 {}
语法结构成为与 std::initializer_list
行为方式完全相似的类型。
考虑您的代码:
user<int> sample { 1, 2, 3, 4, 5 };
如果你仔细想想,这应该意味着 user<int>
的构造函数将被调用,它有 5 个参数。毕竟,如果 user
有一个包含 5 个整数参数的构造函数,那就是这个意思。但这不是您想要的意思,对于 vector<int>
也不是那个意思。为什么?
因为 C++ 的语言有一个关于列表初始化的特殊规则,它检测是否存在一个构造函数,该构造函数采用匹配 braced-init-list 类型的 std::initializer_list
,然后创建一个 std::initializer_list
来传递给这个构造函数。此规则关闭了采用 std::initializer_list
且 没有其他类型 .
您的代码不起作用,不是因为缺少推导指南,而是因为您的 initializer_list
类型在语言方面没有特殊规则。
您无法使用 user-defined 类型重新创建此语言行为。正如你不能使 typeid
return 成为 std::type_info
以外的类型。正如您不能使 enum class byte: unsigned char{};
具有与 std::byte
.