Как исправить ошибку C2679 в шаблонном классе, который используется для возврата разных типов на основе параметра? - PullRequest
0 голосов
/ 27 июня 2018

Я хочу создать шаблонную функцию, которая имеет универсальный тип в качестве возвращаемого типа. Цель функции - инициализировать тип и присвоить ему некоторые значения. Тип определяется переменной int в параметре. По какой-то причине всякий раз, когда я вызываю эту функцию, я получаю сообщение об ошибке:

Ошибка C2679 бинарная '=': не найден оператор, который принимает правый операнд типа 'B' (или нет приемлемого преобразования).

Строка, в которой происходит ошибка, зависит от того, указан ли я в качестве параметра 0 или 1.

Вот пример того, как выглядит код:

class A
{
public:
    A();
    ~A();
    int value;
};

class B
{
public:
    B();
    ~B();
    long long value;
};

template<typename T>
T Load(int const &tp)
{
    T item;

    switch (tp)
    {
        case 0:
        {
            A a = A();
            a.value = 10;
            //... Load file from hard disk and initialize it to this class.
            item = a; //Error if parameter is 1
        }
        break;
        case 1:
        {
            B b = B();
            b.value = 20;
            //... Load different file from hard disk and initialize it to 
            //this class.
            item = B(); //Error if parameter is 0
        }
        break;
    }
}

int main()
{
    A a = Load<A>(0);
}

Знаете ли вы, как исправить эту ошибку?

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Есть что-то, что вы не показываете? Тот факт, что это шаблон класса, означает, что item просто должен быть типом, имеющим член value - вам не нужно явно указывать предполагаемый тип. Я думаю, что вы хотите это:

template<typename T>
T Load(int tp)
{
    T item;

    switch (tp)
        {
        case 0:
            item.value = 10;
            break;
        case 1:
            item.value = 20;
            break;
        }

    return item;
}

A a = Load<A>(0);
B b = Load<B>(1);
0 голосов
/ 27 июня 2018

Нет общего типа между A и B. Таким образом, T не может иметь какого-либо определенного типа.

Давайте поставим себя на место компилятора. Как мы выясним, что такое T?

Давайте попробуем T = A. Это терпит неудачу, когда мы пытаемся сделать это:

T item = B();

Аналогично, T = B завершается неудачно, когда мы пытаемся сделать это:

T item = A();

К сожалению, мы не можем явно создать тип, который работает как с A, так и с B, так как они не имеют общих позиций.


Поскольку вы упомянули, что A и B соответствуют разным типам файлов, позвольте мне предложить решение:

switch(filetype) {
case FILETYPE_A:
    a = A::Load(filename);
    print << a.text << std::endl;  // do stuff with a
    break;
case FILETYPE_B:
    b = A::Load(filename);
    b.show_image();  // do stuff with b
    break;
};

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

Как показано в приведенном выше примере, они не имеют одинаковые возможности (один текст, а другой изображение). Если вы не можете определить общий интерфейс между этими файлами, просто не имеет смысла иметь универсальный тип.

Если вы действительно хотите какое-то общее решение, вы можете подумать:

  • Общий интерфейс класс, который A и B наследуют от
  • Адаптер шаблон
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...