繁体   English   中英

具有相同类型的可变参数模板参数的构造函数无法编译

[英]constructor with variadic template arguments of the same type does not compile

我正在尝试构造一个使用可变参数模板构造函数的类。 模板参数都是相同的类型。

我在 C++ 17 中使用 Visual C++ 编译器,但代码没有生成; 这段代码实际上使编译器崩溃。

这在 C++17 中可能吗?

 struct Alfa {
     template<int... T>
     Alfa(const T&... all_args) {
         std::tuple<T...> data(all_args...);       
     }    
 };

 Alfa alfa(1,2,3,4);

模板参数都是相同的类型。 [...] 在 C++17 中这可能吗?

是的,这是可能的。

但不是以如此简单的方式并且有一些缺点。

您可以编写一个接受不同类型参数的构造函数; 这很简单

 template <typename ... Ts>
 Alfa (const Ts & ... as) 
  { std::tuple<Ts...> data{as...}; } 

但这允许Ts...类型不同。

您可以使用 SFINAE 强加所有类型都相同,如下所示

 template <typename T, typename ... Ts,
           std::enable_if_t<(std::is_same_v<T, Ts> && ...), bool> = true>
 Alfa (T const & a0, Ts const & ... as)
  {
     std::tuple<T, Ts...> data0{a0, as...};       
     std::array           data1{a0, as...};
  }  

所以你的构造启用只有当所有Ts...类型,先上后下T ,是完全一样T

缺点:与

   Alfa alfa{1, 2, 3, 4};

但给出了一个错误

   Alfa alfa{1l, 2l, 3, 4l};  <-- 3 isn't long

因为3可以转换为long1llong )但不是long

所以你可以检查以下Ts...是否可以转换为T ,而不是它们是否相等

 template <typename T, typename ... Ts,
           std::enable_if_t<(std::is_convertible_v<Ts, T> && ...), bool> = true>
 Alfa (T const & a0, Ts const & ... as)
  {
     std::tuple<T, Ts...>             data0{a0, as...};       
     std::array<T, sizeof...(Ts)+1u>  data1{a0, as...};
  }   

但是通过这种方式,您将T赋予其他类型更大的重要性(如果所有Ts...都可以转换为T但不是如果T可以转换为Ts... )所以我想更好的解决方案是检查是否有一个常见的类型

 template <typename ... Ts,
           typename CT = std::common_type_t<Ts...>>
 Alfa (Ts const & ... as)
  {
     std::tuple<Ts...>              data0{as...};       
     std::array<CT, sizeof...(Ts)>  data1{as...};
  }  

您必须决定是否需要非类型模板参数。 您的代码首先说“ T是整数值”,然后尝试像函数签名和tuple模板参数列表中的类型一样使用T

有效的选项是:

 struct Alfa {
     template<class ... Ts>
     Alfa(const Ts&... all_args) {
         std::tuple<Ts...> data(all_args...);       
     }    
 };

 Alfa alfa(1,2,3,4);

这不会对“所有Ts必须相同”的约束进行编码。 没有直接的方法可以做到这一点。 您可以使用static_assert或 SFINAE (请参阅其他答案)。

 template<int... Is>
 struct Alfa {
     Alfa() {
         std::tuple data(Is...); // Using class template argument deduction.
     }    
 };

 Alfa<1,2,3,4> alfa{};

这对类进行模板化,而不是构造函数,这很可能不是您想要的。 它显示了接受编译时整数值(即非类型模板参数包)的语法。 但是您不能对非类型模板参数使用推导,因此必须明确指定它们。 但这对构造函数来说是不可能的!

妥协可能是:

 struct Alfa {
     template<class ... Ts>
     Alfa(const Ts&... all_args) {
         std::tuple<Ts...> data(all_args...);       
     }    
 };

 template<int ... Is>
 auto makeAlfa() { return Alfa(Is...); }

 Alfa alfa = makeAlfa<1,2,3,4>();

暂无
暂无

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

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