可以检测 std::vector 的 C++ 模板化 class 函数

C++ Templated class function that can detect std::vector

如果我有模板 class,我可以执行以下操作来检测是否传递了矢量:

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 函数,但 vector 有。 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 

那么,如何在编译时或运行时结合这两个想法?也就是说,有一个模板化的 class 和一个可以处理向量和非向量的函数?

您正在寻找的是 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";
        }
    }
};

请参阅 for some more talk on the differences. You can also read the cppreference page on if statements 以详细了解一些基本细节。