Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;可变模板构造函数和公共构造函数_C++_Templates_Constructor_C++14_Variadic Templates - Fatal编程技术网

C++ c++;可变模板构造函数和公共构造函数

C++ c++;可变模板构造函数和公共构造函数,c++,templates,constructor,c++14,variadic-templates,C++,Templates,Constructor,C++14,Variadic Templates,类似(c++14)的代码: 在构造函数中没有附加标记的情况下,您可以启用可变构造函数,当且仅当这些参数不允许您使用其他方式构造C 即: template <typename... T, typename = std::enable_if_t<!std::is_constructible<C, T&&...>::value> > C(T&&... ) { } 模板 > C(T&&…{}

类似(c++14)的代码:


在构造函数中没有附加标记的情况下,您可以启用可变构造函数,当且仅当这些参数不允许您使用其他方式构造
C

即:

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

有了这个变化,
cc1{s}
确实调用了
(2)
cc2{“abc”,3}
确实调用了
(1)
,而
cc7{1,2,3,4,5}
将调用
(4)
创建两层构造函数。然后标记调度

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)... )
  {}
};

就像我们在一个答案错误的上下文中实例化的那样,
是可构造的
。实际上,编译器会缓存模板实例化的结果,因此现在
的结果是可构造的
依赖于编译器顺序(我怀疑是ODR冲突)。

这是另一个不使用标记分派的解决方案。在这里,构造函数是按选择的顺序进行测试的,可以使用带有可变模板的简单构造函数,而无需从接口可变模板构造函数完美转发。例如,我可以将构造函数与std::pair参数一起使用,并在其中使用括号初始值设定项列表
{“String”,6}
,而不是显式传递
std::pair(“String”,6)
,等等,如示例所示。该方法不仅可以控制构造函数的优先级,还可以控制其他成员重载的优先级。目前它需要一个助手类

我对不同的元编程技巧不熟悉,这只是一个建议。我不认为它需要改进

#include <type_traits>
#include <cstddef>
#include <iostream>
using namespace std;

您希望保持可变模板和非模板构造函数,并确保它首先调用非模板构造函数;这对吗?你呢?它没有被使用,这是故意的吗?问题是具有正向(通用)引用的构造函数“吃”任何东西,它们比所有其他构造函数都更受欢迎。@Lorenzo Belli U只是表明C是模板。解决问题可能是语义上的,但
C
在您的任何示例中都不是一个模板。我有点困惑:为什么这不会导致无限递归模板实例化?@dyp我相信这个构造函数直到它的声明符结束时才会被考虑。请参阅最后的
int
参数时,可变因子应产生更好的重载。当SFINAE被停用时,它被称为“确实”。所以在这个
是可构造的
检查中似乎考虑了后面的系数。@dyp
intx=0;C{x};标准::cout不应该
是可构造的
接受
?这太棒了,顺便说一句。
是可构造的
应该在不相关的上下文中执行访问检查(即,没有私有的CTOR)。@T.C.修复。通过要求调用私有模板,使它们成为伪私有的。@barry我认为是为了防止
{}
构造
标记。现在调用者必须
标记{0}
,这不能在类之外完成,因为他们不能命名类型
标记
@TobiasHermann,它应该被称为
是\u模板的\u实例
。当且仅当第二个参数是第一个参数模板的实例时,才为真。在这里,我使用它来防止公共构造函数吃掉
标记的构造函数调用。
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)... )
  {}
};
template <typename... T,
      typename = std::enable_if_t<!std::is_constructible<C, T&&...>::value>
       >
C(T&&... ) { }
#include <type_traits>
#include <cstddef>
#include <iostream>
using namespace std;
struct null_helper { static constexpr int const value = 0; };

template<template<unsigned> typename Helper, unsigned order, typename ...TT>
class constructible_from_order
{
    using PrevType = typename conditional<(order < 1), null_helper,
                                           constructible_from_order<Helper, order-1, TT&&...>>::type;
    static constexpr int const prev = PrevType::value;
    static constexpr bool const is_this_constructible = is_constructible<Helper<order>, TT&&...>::value;
  public:
    static constexpr int const value = prev ? prev : is_this_constructible ? order : 0;

}; // template class constructible_from_order

template<template<unsigned> typename Helper, unsigned order, typename ...TT>
using enable_in_order = enable_if<(constructible_from_order<Helper, order, TT&&...>::value == order)>;

template<template<unsigned> typename Helper, unsigned order, typename ...TT>
using enable_in_order_t = typename enable_in_order<Helper, order, TT&&...>::type;
using blob_data = pair<char const*, size_t>;

class C {

    template<unsigned order>
    class helper
    {
      public:
        helper(char const*, size_t) {} // 1

        helper(blob_data const&, blob_data const&) {} // 1

        template<typename T, typename = enable_if_t<(order == 2) && sizeof(T)>>
        helper(blob_data const&, T&&) {} // 2

        template<typename T, typename = enable_if_t<(order == 3) && sizeof(T)>>
        helper(T&&, blob_data const&) {} // 3

        template <class... Ts, typename = enable_if_t<(order == 4) && sizeof...(Ts)>>
        helper(Ts&&... ) {} // 4

    }; // template class helper

  public: // constructors:

    // order 1
    C(char const*, size_t) { cout << "1" << endl; }

    // order 1
    C(blob_data const&, blob_data const&) { cout << "1" << endl; }

    // order 2
    template<typename T, typename = enable_in_order_t<helper, 2, blob_data const&, T&&>>
    C(blob_data const&, T&&) { cout << "2" << endl; }

    // order 3
    template<typename T, typename = enable_in_order_t<helper, 3, T&&, blob_data const&>>
    C(T&&, blob_data const&) { cout << "3" << endl; }

    // order 4
    template <class... Ts, typename = enable_in_order_t<helper, 4, Ts&&... >>
    C(Ts&&... ) { cout << "4" << endl;}

  public: // member functions:

    // order 1
    void fun(char const*, size_t) { cout << "1" << endl; }

    // order 1
    void fun(blob_data const&, blob_data const&) { cout << "1" << endl; }

    // order 2
    template<typename T, typename = enable_in_order_t<helper, 2, blob_data const&, T&&>>
    void fun(blob_data const&, T&&) { cout << "2" << endl; }

    // order 3
    template<typename T, typename = enable_in_order_t<helper, 3, T&&, blob_data const&>>
    void fun(T&&, blob_data const&) { cout << "3" << endl; }

    // order 4
    template <class... Ts, typename = enable_in_order_t<helper, 4, Ts&&... >>
    void fun(Ts&&... ) { cout << "4" << endl;}

}; // class C
int main() {

  char const* str = "aaa";

  // constructors:
  cout << "Constructors: " << endl;
  cout << "1: "; C  c1   {        str,  size_t{5} };
  cout << "1: "; C  cx   { { str, 5 }, { str, 5 } };
  cout << "2: "; C  c2   { { str, 5 },        str };
  cout << "3: "; C  c3   {        str, { str, 5 } };
  cout << "4: "; C  c4   {        str,        str };
  cout << endl;

  // functions:
  cout << "Functions: " << endl;
  cout << "1: "; c1.fun(        str,  size_t{5} );
  cout << "1: "; c1.fun( { str, 5 }, { str, 5 } );
  cout << "2: "; c1.fun( { str, 5 },        str );
  cout << "3: "; c1.fun(        str, { str, 5 } );
  cout << "4: "; c1.fun(        str,        str );
  cout << endl;

} // main
Constructors:
1: 1
1: 1
2: 2
3: 3
4: 4

Functions: 
1: 1
1: 1
2: 2
3: 3
4: 4