Получить метод, который может возвращать более одного типа, используя шаблон - PullRequest
0 голосов
/ 17 апреля 2019

Наличие нескольких get методов для нескольких закрытых членов делает класс довольно грязным.Я хотел бы реализовать один get метод, который может возвращать тот элемент, который мне нужен.

enum TYPE {INT, DOUBLE, DOUBLE2, STRING};

class Foo {
int i     = 1;
double d  = 2.5;
double d2 = 6.0;
string s  = "string";

public:

template<typename T>
T get(TYPE type) {
    switch (type) {
    case INT:
        return i;
    case DOUBLE:
        return d;
    case DOUBLE2:
        return d2;
    case STRING:
        return s;
    }
}

Затем метод будет использоваться следующим образом:

Foo foo;
int integer = foo.get<int>(INT);
double d2   = foo.get<double>(DOUBLE2);

Почему победилэто компилируется?

1 Ответ

3 голосов
/ 17 апреля 2019

Как вы думаете, что произойдет в этом случае?

TYPE t = DOUBLE;
if (rand() % 2 == 0) {
    t = INT;
}

int i = foo.get<int>(t); // t might be INT or DOUBLE

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

Кроме того, когда вы делаете оператор switch, компилятор имеет для компиляции всего оператора switch, даже в тех случаях, которые могут не вызываться.

Представьте, что создается экземпляр функции-члена get<int>:

template<>
auto get<int>(TYPE type) -> int {
    switch (type) { // type might be anything
    case INT:
        return i;   // return int
    case DOUBLE:
        return d;   // return double
    case DOUBLE2:
        return d2;  // return double
    case STRING:
        return s;   // return string
    }
}

Это не может скомпилироваться. Функция явно возвращает int, но в некоторых ветвях она возвращает другие типы.

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

Если вы хотите больше узнать о том, как реализовать такую ​​структуру данных, я предлагаю вам прочитать std::tuple

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...