C++ 具有boost::any等泛型类型的std::tuple

C++ 具有boost::any等泛型类型的std::tuple,c++,c++11,C++,C++11,亲爱的程序员们: 下面的代码让我有些头疼。它尝试向元组添加一个“通用”对象(=可以从任何对象构造的对象),然后复制该元组 #include <tuple> #include <iostream> #include <typeinfo> struct anything { anything() {} anything(const anything&) {

亲爱的程序员们:

下面的代码让我有些头疼。它尝试向元组添加一个“通用”对象(=可以从任何对象构造的对象),然后复制该元组

    #include <tuple>
    #include <iostream>
    #include <typeinfo>


    struct anything
    {
       anything()
       {}

       anything(const anything&)
       {
          std::cout << "Called copy c'tor" << std::endl;
       }

       template<class T>
       anything(T arg)
       {
          std::cout << "Called c'tor with with argument of type " << typeid(arg).name() << std::endl;
          // new T(arg); // causes stack overflow
       }
    };


    int main()
    {
       std::tuple<anything> t;
       //
       std::cout << "Copy constructing t2, expecting copy c'tor to be called." << std::endl;
       std::tuple<anything> t2(t);

       return 0;
    }
#包括
#包括
#包括
构造任何东西
{
任何事
{}
任何东西(常数任何东西&)
{
std::cout键类型;
升压::信号2::信号

Boost信号在调用slot函数之前在内部将参数包装在一个tuple中,这最终会导致堆栈溢出,因为tuple c'tor使用tuple作为参数调用any c'tor,而any c'tor则使用'any of tuple'调用tuple c'tor,依此类推……

如果您查看t你会注意到的

_Tuple_val<_This> _Myfirst; // the stored element
...
template<class _This2,
    class... _Rest2,
    class = typename _Tuple_enable<tuple<_This2, _Rest2...>, _Myt>::type>
    explicit tuple(_This2&& _This_arg, _Rest2&&... _Rest_arg)
    : _Mybase(_STD forward<_Rest2>(_Rest_arg)...),
        _Myfirst(_STD forward<_This2>(_This_arg))
    {   // construct from one or more moved elements
    }

UPD

根据标准std::tuple提供以下构造函数:

template <class... UTypes>
explicit constexpr tuple(const Types&...);

template <class... UTypes>
constexpr tuple(const tuple<UTypes...>&);
模板
显式constexpr元组(const类型&…);
模板
constexpr元组(consttuple&);

显然,您的模板构造函数比元组的复制构造函数更匹配。

让我们看看重载解析:

std::tuple<anything> t2(t);
自<代码>(3)起,此功能就开始工作是根据
是可转换的
来指定的,它在
显式
转换时返回false。但是,这目前被认为是一个缺陷,将来可能会发生变化-因为毕竟,我们在这里显式构造每个方面,所以仍然应该考虑
显式
构造函数!

一旦发生这种情况,就直接复制构造而言,您就有点运气不佳。您必须为
元组
禁用
任何
构造函数?这似乎…不太好。但是在这种情况下,将该构造函数标记为显式
对于复制初始化仍然有效:

std::tuple<anything> t2 = t;
std::tuple t2=t;

由于上述同样的缺陷,现在即使没有标记
任何东西
构造函数
explicit
,它也能工作。

让模板构造函数
explicit
谢谢你的回答。我接受了Barry的,因为它更完整。至少可以说,std::tuple的这种行为似乎不直观。std::tuple是否应该有一个复制构造函数重载来引用non-const:tuple(tuple&other),以确保std::tuple t2(t);行生成一个副本?
template <class... UTypes>
explicit constexpr tuple(const Types&...);

template <class... UTypes>
constexpr tuple(const tuple<UTypes...>&);
std::tuple<anything> t2(t);
explicit tuple( const Types&... args ); // (2) with Types = [anything]

template< class... UTypes >
explicit tuple( UTypes&&... args );     // (3) with UTypes = [std::tuple<anything>&]

tuple( const tuple& other ) = default;  // (8)
tuple(const anything& );             // (2)
tuple(std::tuple<anything>& );       // (3)
tuple(std::tuple<anything> const& ); // (8)
template<class T>
explicit anything(T arg) { ... }
std::tuple<anything> t2 = t;