【问题标题】:How can one construct an object from a parameter pack in a C++ template?如何从 C++ 模板中的参数包构造对象?
【发布时间】:2022-01-13 20:14:27
【问题描述】:

鉴于以下情况,如何从参数包中正确构造未知类型的对象?

template < typename... Types >
auto foo( Types&&... types ) {
    auto result =  Types{ }; // How should this be done?
    // Do stuff with result
    return result;
}

我希望模板函数只能用匹配的类型调用,所以参数包中的所有内容都应该是相同的类型。例如,如果我需要使用decltype,我引用哪个单独的项目并不重要(否则注释掉部分中的相关代码会导致编译错误)。

【问题讨论】:

  • 如果参数包为空,你希望创建什么对象? int? bool?。如果函数需要至少一个参数,只需声明一个带有一个模板参数和一个可能为空的参数包的函数,然后直接使用第一个参数的类型。
  • @SamVarshavchik 轻松修复static_assert( sizeof...( pack ) &gt; 1 );。我也考虑过这种可能性,但现在让我们忽略它并按原样回答问题。假设在另一个场景中使用。

标签: c++ templates c++17 parameter-pack


【解决方案1】:

由于参数包中的所有类型都是相同的,可以先用逗号展开参数包,再用decltype得到最后一个操作数的类型。

template<typename... Types>
auto foo(Types&&... types) {
  auto result = decltype((Types{}, ...)){ };
  // Do stuff with result
  return result;
}

Demo.

【讨论】:

    【解决方案2】:

    这是一种方法(假设我们谈论的是相对简单的类型,可以维持复制):

    template < typename... Types >
    auto foo( Types&&... types ) {
        return std::array{types...}[0];
    }
    

    这是另一种更复杂但有效的方式,它对类型没有额外的限制:

    #include <tuple>
    
    template < typename... Types >
    auto foo( Types&&... types ) {
        using tup_t = std::tuple<Types...>;
        auto result =  std::tuple_element_t<0, tup_t>{}; 
    
        // Do stuff with result
        return result;
    }
    
    
    // auto k = foo(); // compile error
    
    auto z = foo(10); // z is 0-initialized int
    

    【讨论】:

    • 一个有趣的解决方法,如果没有其他人提出更直接的解决方案,可能不得不这样做。谢谢!
    • @cbrng 又加了一个
    【解决方案3】:

    由于参数包中的所有类型都相同,所以可以使用std::common_type_t,它给出了参数包中所有类型都可以转换为的类型。

    template <typename... Types>
    auto foo(Types&&... types) {
        auto result = std::common_type_t<Types...>{};
        // Do stuff with result
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多