C ++可变参数模板构造函数和通用构造函数

罗曼·科波捷夫

像(c ++ 14)这样的代码:

struct S { int a; int b; };

class C
{
  public:
    C(char const*, size_t) {} // 1
    C(S const&) {} // 2
    C(S const*) {} // 3
    template<typename ...T> C(T&& ...) {} // 4

 // C(S) {} // 5
 // C(S*) {} // 6
};

S s { 1, 2 };
C c1 { s }; // calls 4 and not 2
C c2 { "abc", 3 }; // calls 4 and not 1
C c3 { (char const*)"abc", (size_t)3 }; // calls 1 - ok
C c4 { s }; // calls 5 if uncommented
C c5 { &s }; // calls 6 if uncommented
S const s2 {};
C c6 { &s2 }; // calls 3

如果简单构造函数与传递的参数具有相同的签名,则将调用简单构造函数。是否有一些技巧可以像平常一样使用通用构造函数和可变参数模板构造函数,而不复制类,作为参数传递和重载构造函数,例如:

C(S const*) {}
C(S*) {}

并且在构造函数中没有其他标签

Yakk-亚当·内夫罗蒙特

创建两层构造函数。然后标记分派。

template<template<class...>class Z, class T>
struct is_template:std::false_type{};
template<template<class...>class Z, class...Ts>
struct is_template<Z, Z<Ts...>>:std::true_type{};

struct foo {
private:
  template<class T> struct tag{ explicit tag(int) {} };
public:
  foo( tag<std::true_type>, const char*, size_t );
  template<class...Ts>
  foo( tag<std::false_type>, Ts&&...ts );

public:
  foo() = default; // or whatever
  template<class T0, class...Ts,
    std::enable_if_t<!is_template<tag, std::decay_t<T0>>{},int> =0>
  foo(T0&&t0, Ts&&...ts):
    foo( tag<typename std::is_constructible< foo, tag<std::true_type>, T0&&, Ts&&... >::type>{0}, std::forward<T0>(t0), std::forward<Ts>(ts)... )
  {}
};

“ preferred”的ctor前缀为std::true_type,“ preferred”的ctor前缀std::false_type

这具有完美转发的通常缺陷。例如,如果使用初始化程序列表,则将需要另一个“公共” ctor显式地使用该列表。并且函数名称参数不可思议的重载将不起作用。NULL是一个int等等。

您可以想象一个版本,它具有两个层,而不是两个层。is_constructible< ... >相反,面向公众的ctor中子句被某种魔术所代替,该魔术找到了最高N从而tag<N>, blah...可以构造对象(或者最低N,无论您要使用哪种方式)。然后,它返回type tag<N>,然后分派到该层。

使用这样的技术:

template <typename... T,
      typename = std::enable_if_t<!std::is_constructible<C, T&&...>::value>
       >
C(T&&... ) { }

遇到了一个严重的问题,因为我们已经is_constructible错误答案的上下文中实例化在实践中,编译器会缓存模板实例化的结果,因此现在的结果is_constructible取决于编译器的顺序(我怀疑是违反了ODR)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

通过可变参数模板的C ++ 11构造函数继承

如何在C ++中调用可变参数模板构造函数?

C ++ SFINAE双嵌套的initializer_list与可变参数模板构造函数

在C ++中没有匹配的构造函数来初始化可变参数模板

C ++-通过enable_if_t推导参数包(可变模板)构造函数和复制构造函数

返回C ++ 17可变参数模板“构造推论指南”的可变参数聚合(结构)和语法

C ++:可变参数模板和函数重载

具有可变通用引用和复制构造函数的c ++ 11构造函数

构造函数模板可以在类模板的c ++ 17参数推导中引起歧义吗

C ++ 11:可变参数模板函数参数的数量?

C ++中没有参数可变参数模板函数

C ++构造函数模板专业化

带有 std::enable_if 和 std::decay 的 C++ 类构造函数模板

C ++模板构造函数默认参数

编写可变参数模板构造函数

C ++可变参数模板:无法匹配函数

调用类内的函数的C ++ 11可变参数模板

用可变参数模板在C ++中包装函数指针

C ++ 11可变参数模板函数存储

如何在C ++中使用通用引用参数为模板类编写构造函数

可变参数模板和C数组

C ++无法使用模板参数创建模板构造函数

C ++中可变参数构造函数的用途是什么?

如何:将C ++ 14模板函数扩展为可变参数模板,参数

C ++模板函数别名作为可变参数模板参数

C ++构造函数和复制构造函数

C#通用列表作为构造函数参数

C ++:如何在可变参数模板参数上调用带有类型参数的函数?

C ++ 0/1参数构造函数传递给模板构造函数时未按预期进行链接