简体   繁体   English

从模板参数包 c++ 中解包第一个参数

[英]Unpacking first parameter from template parameter pack c++

I'm new with templates, specially with parameter pack and I wonder if I can get the first value from the pack.我是模板的新手,特别是参数包,我想知道是否可以从包中获取第一个值。

For example the following code:例如下面的代码:

template <typename T, typename... Args>
bool register(Args... args) {
    if (!Foo<T>(args..) {
        assert(std::is_same_v<std::string, args...[0]>);
        std::cerr << "Failed call Foo with " + args...[0] + "\n";
    }
}

How do I really get the first value in args... ?我如何真正获得args...中的第一个值?

Worth to note that args.. .值得注意的是, args.. can contain different types (string, boolean, etc.)可以包含不同的类型(字符串、boolean 等)

Simpler in your case seems to change your function into:在您的情况下更简单似乎将您的 function 更改为:

template <typename T, typename Arg, typename... Args>
bool register(Arg arg, Args... args) {
    if (!Foo<T>(arg, args...) {
        assert(std::is_same_v<std::string, Arg>);
        std::cerr << "Failed call Foo with " + arg + "\n";
    }
}

and from the assert, even从断言中,甚至

template <typename T, typename... Args>
bool register(const std::string& s, Args... args) {
    if (!Foo<T>(s, args...) {
        std::cerr << "Failed call Foo with " + s + "\n";
    }
}

else <tuple> provides some useful tools: else <tuple>提供了一些有用的工具:

template <typename T, typename Arg, typename... Args>
bool register(Args... args) {
    if (!Foo<T>(args...) {
        assert(std::is_same_v<std::string,
                              std::tuple_element_t<0, std::tuple<Args...>>);
        std::cerr << "Failed call Foo with "
            + std::get<0>(std::tie(args...)) + "\n";
    }
}

You can use lambda to extract the first parameter:您可以使用 lambda 提取第一个参数:

template<typename T, typename... Args>
bool register(Args... args) {
  if (!Foo<T>(args...)) {
    auto& first = [](auto& first, ...) -> auto& { return first; }(args...);
    static_assert(std::is_same_v<std::string,
                                 std::remove_reference_t<decltype(first)>>);
    std::cerr << "Failed call Foo with " + first + "\n";
  }
}

I normally use the solution described above, just add an explicit extra template parameter for the first parameter.我通常使用上述解决方案,只需为第一个参数添加一个显式的额外模板参数。 If you cannot do that this also works:如果你不能这样做,这也有效:

#include <type_traits>

namespace details
{
    template<typename type_t, typename... args_t>
    struct deduce_first
    {
        using type = type_t;
    };
}

template<typename... args_t>
using first_t = typename details::deduce_first<args_t...>::type;

template<typename... args_t>
bool register_f(args_t&&... args)
{
    static_assert(std::is_same_v<first_t<args_t...>, bool>, "first argument should have type bool");
    return true;
}

int main()
{
    register_f(true, 1.0);
    // register_f(1.0); <== does indeed not complie

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM