在模板参数包上使用类型特征?

met*_*ter 1 c++ templates type-traits c++17 parameter-pack

在下面的示例代码中,我试图检查函数参数是否是指针 std::is_pointer

如果只有一个参数它工作得很好,但是如何使它与更多参数一起工作,例如在参数包中?

#include <type_traits>
#include <iostream>

class Test
{
public:
    template<typename... Params>
    void f(Params... params);

    template<typename T, typename... Params>
    auto sum(T arg, Params... params)
    {
        return arg + sum(params...);
    }

    template<typename T>
    auto sum(T arg)
    {
        return arg;
    }

    int member = 1;
};

template<typename... Params>
void Test::f(Params... params)
{
    // ERROR: too many template arguments for std::is_pointer
    if constexpr (std::is_pointer_v<Params...>)
        member += sum(*params...);
    else
        member += sum(params...);

    std::cout << member;
}

int main()
{
    Test ts;

    // both fail
    ts.f(1, 2);
    ts.f(&ts.member, &ts.member);

    // is that even possible?
    ts.f(&ts.member, 2);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想如果参数不是全部指针或全部不是指针,那么我们有额外的问题,但让我们假设所有参数要么是指针,要么不是。

那么如果参数是指针和非指针的混合呢?

Fur*_*ish 6

您可以使用折叠表达式

#include <iostream>
#include <type_traits>

template <typename... Ts>
void test(Ts... ts) {
    if constexpr ((std::is_pointer_v<Ts> && ...)) {
        std::cout << "yes\n";
    } else {
        std::cout << "no\n";
    }
}

int main() {
    test(new int, new char, new int);
    test(new int, new char, new int, 2);
}
Run Code Online (Sandbox Code Playgroud)

程序的输出:

yes
no
Run Code Online (Sandbox Code Playgroud)

不过要小心你的函数模板签名 - 我建议使用Ts&&... ts而不是Ts... ts,因为const char[]s 是如何处理的。用我原来的例子,test(new int, new char, new int, "hello");会产生一个yes输出,但是用Ts&&... ts,它会产生no