Construct tuple by passing the same argument to each element with explicit constructor

天大地大妈咪最大 提交于 2021-01-23 06:51:12

问题


The following works fine on Visual C++ 2015 Update 2. Note that A is non-copyable and A::A is explicit.

#include <iostream>
#include <tuple>

struct A
{
    explicit A(int i)
    {
        std::cout << i << " ";
    }

    // non-copyable
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};


template <class... Ts>
struct B
{
    std::tuple<Ts...> ts;

    B(int i)
      : ts((sizeof(Ts), i)...)
    {
    }
};


int main()
{
    B<A, A, A, A> b(42);
}

The goal is to pass the same argument to all tuple elements. It correctly outputs:

42 42 42 42

However, it fails to compile on g++ 4.9.2. Among the many messages is the tuple constructor overload that I think should be called:

In instantiation of ‘B<Ts>::B(int) [with Ts = {A, A, A, A}]’:
    33:24:   required from here
    25:30: error: no matching function for call to
       ‘std::tuple<A, A, A, A>::tuple(int&, int&, int&, int&)’
          : ts((sizeof(Ts), i)...)

[...]

/usr/include/c++/4.9/tuple:406:19: note: template<class ... _UElements, class>
    constexpr std::tuple< <template-parameter-1-1> >::tuple(_UElements&& ...)
     constexpr tuple(_UElements&&... __elements)
               ^
/usr/include/c++/4.9/tuple:406:19: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/tuple:402:40: error: no type named ‘type’ in
    ‘struct std::enable_if<false, void>’
       template<typename... _UElements, typename = typename

The function signature is incomplete in the message, but it refers to this one:

template<typename... _UElements, typename = typename               
   enable_if<__and_<is_convertible<_UElements,
                   _Elements>...>::value>::type>                        
explicit constexpr tuple(_UElements&&... _elements)                      
     : _Inherited(std::forward<_UElements>(__elements)...) { }    

My understanding is that is_convertible fails for an explicit constructor. g++ 5.1 and clang 3.5 have similar error messages.

Now, in C++14, 20.4.2.1/10 says: "This constructor shall not participate in overload resolution unless each type in UTypes is implicitly convertible to its corresponding type in Types". This gives me the impression that g++ and clang actually have this right and that Visual C++ is overly permissive.

[edit: It appears that C++17 has removed this restriction and that Visual C++ 2015 follows it. It now says: "This constructor shall not participate in overload resolution unless [...] is_constructible<Ti, Ui&&>::value is true for all i." It looks like "is implicitly convertible" was changed to "is_constructible". However, I still need a C++14 solution.]

I tried removing explicit from the constructor (I'd prefer to keep it). Visual C++ again compiles fine, but both g++ and clang complain about the deleted copy constructor. Because int is now implicitly convertible to an A, I seem to end up in

explicit constexpr tuple(const Types&...)

which would implicitly convert the ints into a bunch of As and then try to copy them. I'm actually not sure how I would ever be able to use the other constructor.

In C++14, how can I get tuple to initialize its elements by passing the same argument to each constructor if the constructors are explicit?


回答1:


In C++ 14, there doesn't seem to be any way of initializing tuple elements when constructors are explicit, because of the is_convertible requirement. I ended up writing a bare-bones implementation of std::tuple myself that is used on C++14 implementations, such as on Debian 8.




回答2:


I have different error with gcc 4.9.2 than you:

main_console.cpp:47:30: error: no matching function for call to 'std::tuple<A, A, A, A>::tuple(int&, int&, int&, int&)' ts((sizeof(Ts), i)...)

Problem is in the constructor B(int i) : ts((sizeof(Ts), i)...) { } and to be honest i do not know how is your constructor working.

When the B constructor looks like: B(int i) : ts(Ts(i)...) { } and with the copy constructor in A it works fine for me.



来源:https://stackoverflow.com/questions/36580855/construct-tuple-by-passing-the-same-argument-to-each-element-with-explicit-const

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!