Search code examples
c++visual-c++stlc++11visual-c++-2010

Filling std::map with std::transform (error: cannot deduce argument)


I'm trying to fill std::map with std::transform. Next code compiles without error:

std::set<std::wstring> in; // "in" is filled with data
std::map<std::wstring, unsigned> out;

std::transform(in.begin(), in.end()
,   boost::counting_iterator<unsigned>(0)
,   std::inserter(out, out.end())
,   [] (std::wstring _str, unsigned _val) { return std::make_pair(_str, _val); }
);

But If I replace string

,   [] (std::wstring _str, unsigned _val) { return std::make_pair(_str, _val); }

with

,   std::make_pair<std::wstring, unsigned>

or

,   std::ptr_fun(std::make_pair<std::wstring, unsigned>)

I get errors:

foo.cpp(327): error C2784: '_OutTy *std::transform(_InIt1,_InIt1,_InTy (&)[_InSize],_OutTy (&)[_OutSize],_Fn2)' : could not deduce template argument for '_InTy (&)[_InSize]' from 'boost::counting_iterator<Incrementable>'
      with
      [
          Incrementable=unsigned int
      ]
      C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm(1293) : see declaration of 'std::transform'
foo.cpp(327): error C2784: '_OutTy *std::transform(_InIt1,_InIt1,_InIt2,_OutTy (&)[_OutSize],_Fn2)' : could not deduce template argument for '_OutTy (&)[_OutSize]' from 'std::insert_iterator<_Container>'
      with
      [
          _Container=std::map<std::wstring,unsigned int>
      ]
      C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm(1279) : see declaration of 'std::transform'
foo.cpp(327): error C2784: '_OutIt std::transform(_InIt1,_InIt1,_InTy (&)[_InSize],_OutIt,_Fn2)' : could not deduce template argument for '_InTy (&)[_InSize]' from 'boost::counting_iterator<Incrementable>'
      with
      [
          Incrementable=unsigned int
      ]
      C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm(1267) : see declaration of 'std::transform'
foo.cpp(327): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous

and so on... Please explain what is the problem is with compilation?

UPDATE: Thanks for answers. I realized, that it is MSVC2010 bug. By the way the line

&std::make_pair<const std::wstring&, const unsigned&>

causes the same error


Solution

  • This is a bug in the Visual C++ library implementation. The following program demonstrates the issue:

    #include <utility>
    
    int main()
    {
        &std::make_pair<int, int>;
    };
    

    This program yields the error:

    error C2568: 'identifier' : unable to resolve function overload
    

    In the C++ language specification, make_pair is not an overloaded function. The Visual C++ 2010 library implementation includes four overloads taking various combinations of lvalue and rvalue references.

    While an implementation of the C++ Standard Library is allowed to add overloads for member functions, it isn't allowed to add overloads for nonmember functions, thus this is a bug.

    The bug was reported and will be fixed in the next version of Visual C++. However, as STL notes in the resolution to that bug, you'll need to make the template arguments to std::make_pair lvalue references:

    &std::make_pair<const std::wstring&, const unsigned&>