Руководство по выводу для списка инициализаторов фигурных скобок
Существует реализация, очень похожая на
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>
собирается использоваться в другом конструкторе класса:
template<typename T>
struct user {
user( initializer_list<T> init_values ) { ... }
};
и намерение использовать обе вещи вместе:
user<int> sample { 1, 2, 3, 4, 5 };
Очевидно, что компилятор не знает, как определить тип списка инициализаторов фигурных скобок, чтобы он использовал initializer_list, как реализовано выше. Я полагаю, что должно быть реализовано какое-то руководство по выводу, чтобы связать мою реализацию initializer_list и список инициализаторов фигурных скобок. Но я понятия не имею, как реализовать такое.
Может ли кто-нибудь посоветовать мне, как реализовать описанное руководство по дедукции?
1 ответ
в среде, где стандартная библиотека C++ недоступна
Такого нет. Хотя автономные реализации C++ могут свободно реализовывать только части стандартной библиотеки, есть некоторые компоненты, которые должны предоставляться всеми допустимыми реализациями C++. входит в число этих компонентов.
Таким образом, если у вас есть действующая реализация C++ на C++11 или более поздней версии, вы должны иметь
<initializer_list>
заголовок и его содержимое. Это необязательно. Если ваша реализация не предоставляет его, то она неисправна.
Причина, по которой это не является необязательным, заключается в том, что важная функциональность (то есть его генерация из braced-init-list) является функцией языка C++ , а не библиотеки. То есть код вне компилятора не может сделать
{}
грамматическая конструкция становится типом, который в точности аналогичен тому, как ведет себя.
Рассмотрим ваш код:
user<int> sample { 1, 2, 3, 4, 5 };
Если подумать, это должно означать, что конструктор
user<int>
будет вызываться, который принимает 5 параметров. Вот что бы это значило, если бы
user
в конце концов, у него был конструктор с 5 целочисленными параметрами. Но это не то, что вы хотите, чтобы это значило, и это не будет означать, что для
vector<int>
. Почему?
Потому что в языке C++ есть специальное правило об инициализации списка, которое обнаруживает наличие конструктора, который принимает a, соответствующий типам braced-init-list, а затем создает для перехода к этому конструктору. Это правило отключает наличие конструктора, который принимает
std::initializer_list
и никакого другого типа .
Ваш код не работает не из-за отсутствия руководств по дедукции, а из-за того, что вы
initializer_list
type не имеет особых правил в отношении языка.
Вы не можете воссоздать это языковое поведение с пользовательским типом. Так же, как вы не можете сделать
typeid
вернуть тип, отличный от
std::type_info
. Так же, как вы не можете сделать
enum class byte: unsigned char{};
вести себя так же, как
std::byte
.