Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.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++ 从std::tuple派生的类的直接初始化失败,而它对std::pair有效_C++ - Fatal编程技术网

C++ 从std::tuple派生的类的直接初始化失败,而它对std::pair有效

C++ 从std::tuple派生的类的直接初始化失败,而它对std::pair有效,c++,C++,有时,我希望通过实际类使用更改我定义的类型 例如,我在此提供了一个示例,说明如何以与类型相同的方式使用结构: using t_int_pair = std::pair< int, int >; struct s_int_pair : public std::pair< int, int > { using std::pair< int, int >::pair; // inherit ctor }; void foo() { auto [a1

有时,我希望通过实际类使用更改我定义的类型

例如,我在此提供了一个示例,说明如何以与类型相同的方式使用结构:

using t_int_pair = std::pair< int, int >;
struct s_int_pair : public std::pair< int, int >
{
    using std::pair< int, int >::pair; // inherit ctor
};

void foo()
{
    auto [a1, a2] = t_int_pair{ 0, 0 };
    auto [b1, b2] = s_int_pair{ 0, 0 };
    // ...
}
使用t_int_pair=std::pair;
结构s_int_pair:public std::pair
{
使用std::pair::pair;//继承
};
void foo()
{
auto[a1,a2]=t_int_对{0,0};
auto[b1,b2]=s_int_对{0,0};
// ...
}
这个很好用

但是:出于任何原因,相同的代码不适用于std::tuple,即,这会产生编译错误:

using t_int_triple = std::tuple< int, int, int >;
struct s_int_triple : public std::tuple< int, int, int >
{
    using std::tuple< int, int, int >::tuple; // inherit ctor
};

void bar()
{
    auto [a1, a2, a3] = t_int_triple{ 0, 0, 0 };
    auto [b1, b2, b3] = s_int_triple{ 0, 0, 0 }; // ERROR: cannot decompose class type 'std::_Tuple_impl<0, int, int>'
    // ...
}
使用t_int_triple=std::tuple;
结构s_int_triple:public std::tuple
{
使用std::tuple::tuple;//继承
};
空条()
{
auto[a1,a2,a3]=t_int_三元组{0,0,0};
auto[b1,b2,b3]=s_int_triple{0,0,0};//错误:无法分解类类型'std::\u Tuple\u impl'
// ...
}
有人知道为什么会这样吗

有办法解决这个问题吗

我用clang、gcc和msvc在编译器浏览器上测试了这一点

感谢您的帮助

问候,


Zoppo

Pair是包含公共成员的聚合,而tuple则不是

您的继承自对正在使用聚合结构化绑定

Tuple使用Tuple机制。有些元组机制不能与继承一起工作,这是有充分理由的

因此,您需要专门化
std::tuple\u size
以公开tuple大小

struct s_int_triple : public std::tuple< int, int, int >
{
  using std::tuple< int, int, int >::tuple; // inherit ctor
};
namespace std{
  template<>
  class tuple_size<::s_int_tuple>:public std::integral_constant<std::size_t, 3>{};
  template< std::size_t I >
  class tuple_element<I,::s_int_tuple>:public tuple_element<I, std::tuple<int,int,int>>{};
}
struct s_int_triple:public std::tuple
{
使用std::tuple::tuple;//继承
};
名称空间标准{
模板
类元组大小:public std::integral_常量{};
模板
类tuple_元素:公共tuple_元素{};
}
结构化绑定应该可以工作


是的,这很糟糕。

我从将指令分成两部分开始(使用旧式初始化绕过与
std::initailizer\u列表相关的任何问题,如果有的话):

编译器错误为:

main.cpp:27:10: error: cannot decompose class type ‘std::_Tuple_impl<1, int, int>’: its base classes ‘std::_Head_base<2, int, false>’ and ‘std::_Head_base<1, int, false>’ have non-static data members
   27 |     auto [b1, b2, b3] = s;
      |          ^~~~~~~~~~~~
宾果!这是一个非静态数据成员

现在是找到结构化绑定分解的适当规则的时候了。我们去那里,直接到“案例3”:

E的每个非静态数据成员必须是E的直接成员与E的相同基类,并且当命名为E.name时,必须在结构化绑定的上下文中格式良好。E可能没有匿名工会成员。标识符的数量必须等于非静态数据成员的数量

这里我们有了答案:从
std::tuple
派生的类也继承了其他几个类,其中一些类定义了非静态成员

这一现象的简单例子:

struct A
{
  int x;
};

struct B: public A
{
  int y;
};

int main()
{
  B obj;
  auto [a, b] = obj;
}
导致

main2.cpp:14:8: error: cannot decompose class type ‘B’: both it and its base class ‘A’ have non-static data members
所以现在我们遇到了一个真正的难题:如果
std::tuple
继承自不同的类,并且每个类都定义了一个非静态成员,那么为什么我们可以对tuple使用结构化绑定呢?我们回到cppreference,看到
std::tuple
是上述情况3的一个例外。编译器必须以自己特殊的方式处理标准元组和类似类。换句话说,
std::tuple
和类似tuple的类由案例2处理,但任何其他类或结构都由限制性更大(非常普遍)的案例3处理


因此,要使您的程序编译,您必须使您的类“类似元组”,如上面引用的源代码所述。我完全不知道这是否可能——我想这应该单独问一个问题。如何做到这一点在@yakk adam nevraumont的回答中进行了描述

不,初始化工作正常,失败的是结构化绑定。这是有原因的。我很惊讶从std对继承允许结构化分解工作。也许是公众成员?这可能就是为什么。(
std::get
自动工作,因为类有
std::tuple
作为基本情况,对吗?)@user2是的,重载解析考虑基本情况,而模板专门化不考虑。非常感谢。。。但我认为我不会在STD命名空间中实现某些东西(AFAIK C++标准不允许它)。因此,我想我会咬紧牙关,实现一个函数,在用结构替换我的类型之后,在它不编译的任何地方使用它。@zoppo你特别允许为依赖于你的类型的类型指定某些特征,这是明确允许的,也是设计允许的。这是你应该怎么做的。非常感谢你提供的详细信息,现在我明白为什么它不能工作了。
struct A
{
  int x;
};

struct B: public A
{
  int y;
};

int main()
{
  B obj;
  auto [a, b] = obj;
}
main2.cpp:14:8: error: cannot decompose class type ‘B’: both it and its base class ‘A’ have non-static data members