This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [c++0x] pair's variadic constructor (N2369, 20.2.3.4)


On Aug 27, 2007, at 1:40 PM, CoffeeBuzz wrote:


template<typename _U1, typename... _Args>
pair(_U1 && __x, _Args &&... __args)
: first(std::forward<_U1>(__x)), second(std::forward<_Args>(__args)...) {}


I can't seem to find information as to why this was added to the standard.
It seems to me that its just some syntatic sugar to initializing pairs. For
example:
pair<int, pair<double, string>> p(1, 2.3, "Hi mom.");
struct A { A(int, int) {} };
pair<int, A> p(1,2,3);

Actually the motivation is more than syntactic sugar. It stems from the recent "emplace" work in the associative containers.


class map
{
...
template <class... Args> pair<iterator, bool> emplace(Args&&... args);
template <class... Args> iterator emplace(const_iterator position, Args&&... args);
...
};


Since the value_type of the map is a pair, the variadic constructor for the pair maps nicely to the variadic emplace args for (unordered) (multi)map.

However, after implementing the full spec, I get some odd deduction behavior
in all the ctor overloads. Take the following mock-pair class:


template <typename T1, typename T2>
struct P {
   P(){}
   P(P && p) {}
   P(T1 const& t1, T2 const& t2){}

   template <typename U1, typename U2>
   P(P<U1,U2> const& p) {}

   template <typename U1, typename U2>
   P(U1&& u1, U2&& u2) {}

   template <typename U1, typename U2>
   P(P<U1,U2> && p) {}

   template <typename U, typename... Args>
   P(U && u, Args&&... args) {cout << "why?"; }
};

When I compile the following code:
P<int,int> p1(1,2);
P<int,int> p2(p1);

It seems that the construction of p2 is not done by P(P<U1,U2> const& p) or
P(P&& p) as I might have expected. Instead, P(U && u, Args&&... args) is
chosen with U being type P<int, int>& and Args is no type (empty pack).


Now this is an issue because in the pair, this variadic ctor forwards u to
"first" and args to "second" but first is type int, and not P<int,int>& and
thus errors. So, how do you stop this behavior?

I agree we have a problem here. I believe the answer is going to be along the lines of:


template<class U, class Arg0, class... Args> pair(U&& x, Arg0&& arg0, Args&&... args)
: first(std::forward<U>(x)), second(std::forward<Arg0>(arg0), std::forward<Args>(args)...)


This isn't fully tested, and I haven't tested it against the emplace functions. I've contacted the author of the emplace work for consultation on this. When we get an issue up on it, I'll post a link to that issue here.

Thanks for reporting this.

-Howard


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]