Руководство по выводу для списка инициализаторов фигурных скобок

Существует реализация, очень похожая на 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_listtype не имеет особых правил в отношении языка.

Вы не можете воссоздать это языковое поведение с пользовательским типом. Так же, как вы не можете сделать typeidвернуть тип, отличный от std::type_info. Так же, как вы не можете сделать enum class byte: unsigned char{};вести себя так же, как std::byte.

Другие вопросы по тегам