Вопрос

I have a strange problem that I cannot bind this template member function, all this code compiles: http://ideone.com/wl5hS8

It's a simple code: I have a ExecutionList which should hold callable functions in a std::vector. I can now add functions by calling ExecutionList::addFunctor. But there, I cannot bind to template<typename T> void Functor::calculate(T * t). I am asking me why, what is missing here, the compiler cannot somehow deduce what I have written in

m_calculationList.push_back( std::bind(&T::calculate<Type>, extForce, std::placeholders::_1 ) );

*Error: *

error: expected primary-expression before ‘>’ token
                 m_calculationList.push_back( std::bind(T::calculate<Type>, extForce, std::placeholders::_1 ) );
                                                                     ^

The Code:

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

struct MyType{
    static int a;
    int m_a;
    MyType(){a++; m_a = a;}

    void print(){
        std::cout << "MyType: " << a << std::endl;
    }
};
int MyType::a=0;


struct Functor{

    static int a;
    int m_a;

    Functor(){a++; m_a = a;}

    // Binding this function does not work 
    template<typename T>
    void calculate(T * t){}

    // Binding this function works!!!
    void calculate2(MyType * t){
        std::cout << " Functor: " << m_a <<std::endl;
        t->print();
    }

};

int Functor::a=0;

// Binding this function works!!!
template<typename T>
void foo( T * t){}

class ExecutionList{
    public:
        typedef MyType Type;

        template<typename T>
        void addFunctor(T * extForce){
            //m_calculationList.push_back( std::bind(&T::calculate<Type>, extForce, std::placeholders::_1 ) );   /// THIS DOES NOT WORK
            m_calculationList.push_back( std::bind(&T::calculate2, extForce, std::placeholders::_1 ) );
            m_calculationList.push_back( std::bind(&foo<Type>, std::placeholders::_1 ) );
        }


        void calculate(Type * t){
            for(auto it = m_calculationList.begin(); it != m_calculationList.end();it++){
                (*it)(t); // Apply calculation function!
            }
        }

    private:
        std::vector< std::function<void (Type *)> > m_calculationList;
};



int main(){
    MyType b;
    ExecutionList list;
    list.addFunctor(new Functor());
    list.addFunctor(new Functor());
    list.calculate(&b);
}
Это было полезно?

Решение

Looks like you're missing the template keyword. If T is a template parameter and T::calculate refers to a template you need to tell the compiler that calculate is a template and not some static variable which you try to compare using the less-than operator with something else:

T::template calculate<Type>

I ran into the exact same problem a couple of years ago but today (post C++11) I would probably solve it with a lambda which is simpler:

std::function<void(Type*)> func = [obj](Type*param){obj.calculate(param);};

Anyhow, try to reduce the number of new uses. Look for a better way to manage your resources. Your code seems to leak a couple of functors.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top