Параметры не типового шаблона, такие как size_t
, который принимает std::get<>
, должны быть константами времени компиляции.
Ваш auto a
не является постоянной времени компиляции. В вашем конкретном случае вы можете доказать, что значение a
в этой точке никогда не изменится и всегда будет 0
.
Но C ++ - это строго типизированный язык, который опирается на явные типы, предоставляемые программистом. В момент вычисления std::get<a>
единственное, что C ++ позволяет себе знать о a
, - это то, что это неконстантная локальная переменная non-constexpr типа std::size_t
.
Таким образом, если std::get<a>
работает, то должны:
int main(int argv, char ** argc) {
UserInfo s{"Edmund", "edmund@page.me", "Denver street 19"};
std::size_t a = argv; // number of arguments
std::cout << std::get<a>(s) << std::endl;
}
std::get<std::size_t>
- это функция nothrow
, и она не может завершаться ошибкой во время выполнения. Если вы вызываете этот код с 100 аргументами, приведенный выше код не может работать.
Во-вторых, в то время как ваш UserInfo
имеет 3 идентичных типа, std::get<size_t>(tuple<a,b,c>)
работает, когда типы не совпадают. Так
using UserInfo = std::tuple<int, std::string, double>;
тогда std::get< argv >( some_user_info )
тоже должно работать. И в этом случае тип, который он возвращает, может быть любым из трех типов - но C ++ требует, чтобы все выражения имели тип one .
Краткая версия - "так говорит языковой стандарт". Более длинная версия - «В общем случае ваш код не работает».
Теперь вы можете решить свой код в вашем конкретном случае с небольшими изменениями.
using UserInfo = std::array<std::string, 3>;
теперь UserInfo
, как известно, имеет 3 типа униформы.
std::cout << s[a] << std::endl;
и теперь вы передаете индекс, и, поскольку аргумент []
не является параметром не типового шаблона, он может изменяться во время выполнения.
[]
разрешено выполнять UB, если индекс выходит за пределы. (std::get<a>
нет).
Теперь, C ++ может развиваться, и новый стандарт может бросить некоторую магию и каким-то образом обнаружить ваш особый случай и разрешить сбой std во время выполнения и т. Д. Но тогда каждый вызов std::get
является возможной ошибкой во время выполнения, а до этого не было; поверхность тестирования вашего приложения только что взорвалась.
Черт, он может автоматически обнаружить, что auto a = blah
был инициализирован с помощью константного выражения в предыдущей строке, и использовать его на следующей строке автоматически будет константным выражением.
Но тогда программист, который знал, что они делают, заменив вызов get_proper_a()
на 3
для отладки, мог бы своим кодом внезапно изменить поведение, поскольку информация секретного типа «просачивается» в код. И когда get_proper_a()
, который фактически возвращает 3
(но компилятор не может этого доказать), запускается, код прерывается во время выполнения.