Какой тип делает static auto constexpr t = {"red", "black", "green"};выводить? - PullRequest
0 голосов
/ 27 сентября 2018

Итак, я возился с каким-то кодом и решил, что мне нужен какой-то список строк ... и тогда я подумал - я не могу потрудиться выяснить, какие типы использовать и так далее, поэтому япросто вставил бы его в автоматическую переменную, например:

static auto constexpr t = {"red", "black", "green"};

и скомпилированный код.Отлично, так как это:

static auto constexpr str = "green";

наследуется от char[] Я предполагал, что {"red", "black", "green"} могут быть * char [] или что-то подобное, поэтому я мог бы написать:

std::cout << "value 1 is: " << t[1] << std::endl;

, что дает мне ошибку:

main.cpp: 18: 56: error:нет соответствия для 'operator []' (типы операндов: 'const std :: initializer_list' и 'int')

Итак, я предполагаю, что типом является "initializer_list"?Есть ли способ сделать что-то вроде: t[1], чтобы получить строку "черный" (при условии, что индекс начинается с 0)?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Объект типа std :: initializer_list - это легкий прокси-объект, который обеспечивает доступ к массиву объектов типа const T. (https://en.cppreference.com/w/cpp/utility/initializer_list)

Он не имеетфункция-член operator[], тем не менее, единственные средства доступа, * std::initializer_list::begin и std::initializer_list::end. Например:

#include <iostream>
#include <initializer_list>
#include <stdexcept>

namespace my {

template <typename T>
constexpr auto get(std::initializer_list<T> lst, std::size_t i)
{
    if ( i >= lst.size() )
        throw std::out_of_range("Out of bounds access.\n");
    return *(lst.begin() + i);   
}

template <std::size_t I, typename T>
constexpr auto get(std::initializer_list<T> lst) 
{
    // Note: /5751195/staticassert-v-initializerlist-size
    if ( I >= lst.size() )
        throw std::out_of_range("Out of bounds access.\n");
    return *(lst.begin() + I);   
}

}

int main()
{
    // Note: https://stackoverflow.com/questions/16063123/is-it-legal-to-declare-a-constexpr-initializer-list-object
    static constexpr auto t = {"red", "black", "green"};

    std::cout << my::get(t, 1) << '\n' << my::get<2>(t) << '\n';
}
0 голосов
/ 27 сентября 2018

Итак, я предполагаю, что тип "initializer_list"?

Да.

Есть ли способ сделать что-то вроде: t [1], чтобы получить строку "black" (при условии, что индекс начинается с 0)?

Использование std::array, которое хорошо сочетается с выводом типа шаблона класса C ++ 17:

static auto constexpr t = std::array{"red", "black", "green"};

std::cout << t[1] << "\n"; // outputs 'black'

constexpr -ness сохраняется, есливы передаете константы времени компиляции в operator[] или std::get.

constexpr const char* black = t[1];
constexpr const char* red = std::get<0>(t);
...