Вопрос

У меня есть программа, которая должна задавать тип вектора при выполнении программы (в соответствии со значением в файле конфигурации).

Я пробовал это:

int a = 1

if(a == 1)  vector<int> test(6);
else  vector<unsigned int> test(6);

test.push_back(3);

Но это дает мне:

Error   1   error C2065: 'test' : undeclared identifier

Я не совсем уверен, почему, но я думаю, что это потому, что вектор на самом деле не определен во время компиляции, поэтому компилятор не может работать с ним во время компиляции остальной части кода.

Есть ли способ определить тип вектора во время выполнения, аналогичный тому, который я пытался описать выше? Я попытался создать одну версию вне if, а затем удалить ее и переписать новую версию внутри IF. Это, однако, кажется неправильным, и я все равно не могу заставить его работать. спасибо.

Это было полезно?

Решение

Причина, по которой это не работает, заключается в том, что вы объявляете векторы внутри блока if- и else соответственно, поэтому они выходят за рамки, когда этот блок заканчивается.

  

Есть ли способ определить тип вектора во время выполнения, аналогичный тому, который я пытался описать выше?

Нет, тип переменной должен быть известен во время компиляции. Единственный вариант - поместить строку test.push_back(3), а также любой следующий код, который обращается к test, в блок if и else или избежать дублирования кода во второй шаблонной функции. Это может выглядеть так:

template <class T>
do_something_with_test(vector<T>& test) {
    test.push_back(3);
    // work with test
}

void foo() {
    int a = 1

    if(a == 1) {
        vector<int> test(6);
        do_something_with_test(test);
    }
    else {
        vector<unsigned int> test(6);
        do_something_with_test(test);
    }
}

Другие советы

Точная причина ошибки, которую вы получаете, довольно тонкая для начинающего, и она включает в себя область действия переменной test, которую вы создаете. Проще говоря, вы создаете вектор внутри оператора if, но к тому времени, когда вы собираетесь его использовать, он больше не существует, потому что он вышел из области видимости.

Я переформатировал ваш код в скобках, чтобы сделать этот эффект более заметным. Обратите внимание, что моя версия семантически эквивалентна вашей и выдает ту же ошибку.

if(a == 1)
{
  vector<int> test(6);
}
else
{
  vector<unsigned int> test(6);
}

test.push_back(3);

Тем не менее, то, что вы пытаетесь сделать, кажется немного странным, и я должен задаться вопросом, какова ваша конечная цель. Это не значит, что нет способов сделать то, что вы, похоже, хотите сделать, но мне нужно знать, каковы ваши критерии успеха, прежде чем я смогу предложить более подходящий метод.

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

union DataType
{
    int intVal;
    unsigned uintVal;
}
std::vector<DataType> vec;

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

Удачи!

Вы могли бы взглянуть на boost :: any чтобы достичь чего-то похожего.

Установка типа вектора (он же создание шаблона ) всегда происходит во время компиляции. Для получения дополнительной информации ознакомьтесь со статьей в Википедии метапрограммирование шаблонов .

если вам действительно нужен полиморфный тип, возможно, вы могли бы взглянуть на класс boost :: option или что-то подобное;
Это разработано для имитации некоторых поведений динамических языков в C ++ и обычно используется для взаимодействия (или реализации) с ними. Вы можете создать " vector < Вариант & Gt; " и a.push_back (Variant ((unsigned int) ..).) конструкторам для отправляемых значений требуется тип времени компиляции.

Также было бы возможно создать векторизованный вариантный класс, который будет хранить информацию о типе для всей коллекции, если вы ожидаете, что значения будут однородными.

но гораздо более вероятно, что вы можете достичь желаемого конечного результата без такого механизма, возможно, переделав вашу программу, чтобы избежать проверок типов во время выполнения (что, скорее всего, сведет на нет некоторые преимущества использования C ++ по сравнению с другим языком в первую очередь). ).

Вы можете написать зависимые от типа детали в виде шаблонов (как предложено выше) и выбрать альтернативный путь к коду на основе установленного параметра файла конфигурации & amp; отправлен один раз. Этот стиль кодирования становится немного проще в c ++ 0x с помощью 'auto' и decltype ().

Особый случай значений со знаком и со знаком включает в себя предоставление еще одного бита, который звучит необычно, или незначительного преимущества по сравнению с добавленной сложностью, но я легко могу представить себе тот, кто хочет реализацию, которая может переключаться между плавающей запятой одинарной и двойной точности, например .

Еще одним простым вариантом будет установка времени компиляции для типа (например, введенного как определение из настроек сборки или make-файла), а затем распространение нескольких версий вашей программы, что может иметь смысл в некоторых обстоятельствах. Тем не менее, уже предложенные шаблоны, скорее всего, будут наиболее полезным вариантом.

В вашем примере у вас есть независимые экземпляры переменной test, созданные в каждой ветви вашего оператора if, каждый из которых немедленно выходит за рамки. Поэтому, когда компилятор попадает в test.push_back(3);, в области видимости нет переменной int, поэтому возникает ошибка.

Чтобы решить вашу проблему, вы не можете бороться с системой типов: если предположить, что unsigned int и vector<int> являются реальными типами, о которых вам было бы лучше, используйте <=> повсюду, предполагая, что вы не на самом деле нужен полный диапазон беззнаковых int.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top