diverscuba23
diverscuba23

Reputation: 2185

initializer list to initialize std::vector<std::function<bool(std::string)> > gives error with g++ 4.9.0 but compiles fine with Visual Studio 2013

The following reduced case will compile and run fine in MSVS 13, but with gcc 4.9.0 I get the error:

cannot convert from <brace-enclosed initializer list> to std::vector(std::function<bool(std::string)>>.

#include <iostream>
#include <functional>
#include <vector>
#include <string>  

template<typename F> class Foo
{
public:
    Foo(int a) : wombat(a) {};
    ~Foo() {}

    bool get_result() { return result; }

protected:
    template<typename A> bool do_something(std::string& s, A& a, A b, A c);

    bool result;
    int wombat;
};

template<typename F> template<typename A> bool Foo<F>::do_something(std::string& s, A& a, A b, A c)
{
    if ( a > b && a < c)
    {
        std::cout << s << std::endl;
        return true;
    }
    return false;
}

struct Tim
{
    int age;
    float weight;
};

class Bar : public Foo<Tim>
{
public:
    Bar(int a) : Foo<Tim>(a) {};
    ~Bar() {};

    void do_somethings();
};

void Bar::do_somethings()
{
     Tim t;
     t.age = 15;

     std::vector<std::function<bool(std::string)> > my_list = {
         std::bind(&Bar::do_something<int>, this, std::placeholders::_1, std::ref(t.age), 10, 100)
     };   // Error shows up here

     for( auto v : my_list) { result = v("howdy"); }
}

int main(int argc, char** argv)
{
    Bar b(200);
    b.do_somethings();
    return 0;
}

Am I doing something wrong, or miss something about how initializer lists are supposed to work?

Upvotes: 0

Views: 1129

Answers (1)

Praetorian
Praetorian

Reputation: 109219

template<typename A> bool do_something(std::string& s, A& a, A b, A c)

The type of do_something's first parameter is std::string&, not std::string. Change the parameter type of the std::function accordingly.

std::vector<std::function<bool(std::string&)> > my_list = ...
//                                        ^

For the same reason, you cannot invoke the std::function instance as v("howdy") because that involves the construction of a temporary std::string object, which cannot bind to a non-const lvalue reference parameter. Use this instead

std::string s("howdy");
for( auto v : my_list) { result = v(s); }

Another option would be to change the function parameter type to std::string const& if it doesn't need to modify the argument.

Live demo


Also be aware that you're making a copy of each vector element in the for loop. You may want to change that to

for( auto& v : my_list)

Upvotes: 1

Related Questions