Если у меня есть шаблонный класс, я могу сделать следующее, чтобы определить, был ли передан вектор:
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
Итак, как я могу объединить эти две идеи, во время компиляции или во время выполнения? То есть есть шаблонный класс с функцией, которая может обрабатывать векторы и не векторы?