3

I'm trying to compile code like this using both GCC 4.4.7 and MSVC 2010:

// test.cpp
// use g++ -c test.cpp to attempt compile this 

#include <map>
#include <numeric>
#include <algorithm>

struct A
{
        A() : v1(0), v2(0) {}
    int v1, v2;
};

typedef std::map<int, A> A_map;

void fill_map(A_map& m); // external function

A process()
{
        A_map m;
        fill_map(m);
        A a;
        if(!m.empty())
        {
                struct Aggregate
                {
                        A operator()(const A& left, const A_map::value_type& right)
                        {
                                A result;
                                result.v1 = left.v1 + right.second.v1;
                                result.v2 = std::max(left.v2, right.second.v2);
                                return result;
                        }
                };
                A a0;
                a = std::accumulate(m.begin(), m.end(), a0, Aggregate());
        }
        return a;
}

While MSVC2010 compiles this nicely, GCC 4.4.7 gives following error:

test.cpp: In function ‘A process()’:
test.cpp:33: error: no matching function for call to ‘accumulate(std::_Rb_tree_iterator<std::pair<const int, A> >, std::_Rb_tree_iterator<std::pair<const int, A> >, A&, process()::Aggregate)’

Any ideas why so and how to fix this? Ideas like completely rewrite code using C++11 lambdas do not work - need exactly this code.

ivan.ukr
  • 2,853
  • 1
  • 23
  • 41
  • 2
    1. Is that the *complete* error message (including the candidates and why they fail, if any)? 2. Are you building as C++11? – Angew is no longer proud of SO Jan 19 '15 at 16:15
  • 3
    The actual error is about using local type as a template argument. Looks like before C++11 it was [not allowed](http://stackoverflow.com/questions/5751977/local-type-as-template-arguments-in-c) – Predelnik Jan 19 '15 at 16:22
  • 2
    Note that compiling with `-std=c++0x` won't help you because support for this specific C++11 feature was only added in GCC 4.5. – interjay Jan 19 '15 at 16:27
  • Thank you for the suggestion. I'm compiling for C++ 2003. I am trying to move out the struct Aggregate. – ivan.ukr Jan 19 '15 at 16:27
  • That works, when I have moved struct Aggregate out of the function process(). So thank you again for the correct suggestion! – ivan.ukr Jan 19 '15 at 16:32

1 Answers1

4

C++03 does not allow for the instantiation of templates with local types. If you can't use C++11 or C++14, you can fix that problem by moving the definition of Aggregate outside of the process function. For good measure, make its operator() a const member.

#include <map>
#include <numeric>
#include <algorithm>

struct A
{
    A() : v1(0), v2(0) {}
    int v1, v2;
};

struct Aggregate
{
  A operator()(const A& left, const A_map::value_type& right) const
  {
    ....
  }
};

void fill_map(A_map& m); // external function

A process()
{
  ....
}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480