C ++ Шаблонная функция класса, которая может обнаруживать std :: vector - PullRequest
0 голосов
/ 24 февраля 2020

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

template<typename T> struct is_vector { static const bool value=false; };
template<typename T> struct is_vector<std::vector<T>> { static const bool value=true; };

template<class T>
class Parser {
public:
    Parser() {}
    void parse(T obj) {
        if (is_vector<T>::value) {
            std::cout << "vector\n";

            //obj.push_back(T {});
        }
        else {
            std::cout << "not vector\n";
        }
    }
};

int main() {
    Parser<int> p1;
    p1.parse(123);

    Parser<std::vector<int>> p2;
    p2.parse({ 1, 2, 3});

    return 0;
}

Вывод:

not vector
vector

Я могу обнаружить вектор, но компилятор жалуется, когда я раскомментирую вызов push_back:

main.cpp: In instantiation of ‘void Parser<T>::parse(T) [with T = int]’:
main.cpp:26:14:   required from here
main.cpp:15:17: error: request for member ‘push_back’ in ‘obj’, which is of non-class type ‘int’
             obj.push_back(T {});
             ~~~~^~~~~~~~~

Очевидно, что int не имеет функции push_back, но вектор имеет. Вызов is_vector оценивается во время выполнения, но push_back перехватывается во время компиляции.

С частичной специализацией шаблонов я могу делать то, что хочу:

template<typename T>
void parse(T obj) {
    std::cout << "not vector: " << obj << "\n";
}

template<typename T>
void parse(std::vector<T> obj) {
    std::cout << "is vector\n";
    for (auto i : obj) std::cout << i << " ";

    obj.push_back(T {});

    std::cout << "\n";
    for (auto i : obj) std::cout << i << " ";
    std::cout << "\n";
}

int main() {
    parse(1);
    parse('a');
    parse(std::vector<int> { 1, 2, 3 });

    return 0;
}

Вывод:

not vector: 1
not vector: a
is vector
1 2 3 
1 2 3 0 

Итак, как я могу объединить эти две идеи, во время компиляции или во время выполнения? То есть есть шаблонный класс с функцией, которая может обрабатывать векторы и не векторы?

1 Ответ

1 голос
/ 24 февраля 2020

То, что вы ищете, - это новая функция в C ++ 17, if constexpr. Это то же самое, что и обычный if, за исключением того, что условие оценивается во время компиляции, и при создании экземпляра ветки (веток) отбрасывает неиспользуемую ветку во время компиляции. Отброшенная ветвь не нуждается в правильном формировании. Итак, для вашего примера:

template<class T>
class Parser {
public:
    Parser() {}
    void parse(T obj) {
        if constexpr (is_vector<T>::value) {
            std::cout << "vector\n";

            obj.push_back(T {});
        }
        else {
            std::cout << "not vector\n";
        }
    }
};

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

...