tags:

views:

353

answers:

5

Is there a way to pass foo_ around outside of main? I saw something about Boost in another question regarding functors. That looks like it may work. Here's the answer mentioning Boost in that question. If I can, I would like to avoid Boost.

#include <iostream>

int main()
{
    class foo {
        public:
        void operator()() {
            std::cout << "Hello" << std::endl;
        }
    };

    foo foo_;
    foo_();
    return 0;
}
A: 

EDIT: this does not appear to be valid C++ although some copilers take it without complaint.

well if you have something accepting functors as a template parameter, you could pass anything to it behaving as a functor, although I'm not entirely sure that is what you're after?

template< class tFunctor >
void UseFunctor( const tFunctor& func )
{
  func();
}

int main()
{
  foo foo_;
  UseFunctor( foo_ );
}
stijn
What's invalid with this is that your `func` is a _`const`_ reference, while Scott's `operator()()` isn't `const`. I always recommend to make the function call operator `const` if you can, but the std lib's way to deal with this is to assume function objects are cheap to copy around and never even bother with `const`: `template<class Func> void UseFunctor(Func uunc)`.
sbi
+4  A: 

No, currently local types aren't allowed to go into templates (otherwise you could've used boost or std::tr1::function). However, you could maybe do it OOP, where Foo inherits something (that has a virtual opeator() func that your foo implemen ts) and you pass a ptr to Foo around instead.

Marcus Lindblom
What goes into `boost::function` as a template parameter isn't the callable thing itself, but a generic compatible function prototype. For `foo` that would be `void()` - the signature of a function that takes no arguments and returns nothing.
sbi
@sbi: Have you tried it? The constructor of `function` would still be templated, and would still have to use the local type as a template parameter.
UncleBens
@sbi: it would work if you took the adress of ´foo::operator()´, but you can't store a Foo object in ´boost::function´
Marcus Lindblom
sbi
A: 

I don't think it is possible to invoke a member of a class that is not defined in the current scope. The functor in this case retains no state and behaves like a function that takes no parameters and returns no value, so you could assign an instance of it to a raw function pointer. However, it is then no longer a foo: it is just a function pointer.

One solution is to derive foo from a pure virtual base class defined at global scope, such as:

class base
{
public:
    void operator()() { doit(); }
protected:
    virtual void doit() = 0;
};

int main()
{
    class foo
    {
    public:
        void operator()() { doit(); }
    protected:
        virtual void doit()
        {
            std::cout << "Hello" << std::endl;
        }
    };
 }

You can now pass an instance of foo around as base, and the virtual doit() method will be invoked as expected.

Conal
"I don't think it is possible to invoke a member of a class that is not defined in the current scope." That's nonsense. Whenever function objects are you rarely ever call a member function of a class that's defined in the current scope. (If you pass a function object to `std::for_each()`, it's `operator()` is called in of that function, but it's certainly not defined in its scope.)
sbi
@sbi - The problem is not with directly calling the operator(), but with calling the foreach.If you have: void MyFunc() {< Define class foo here >}Then you can't refer to 'foo' outside of MyFunc. You have to send it somehow (but of course you know that already). I think using inheritance is a legitimate solution, so no need to vote it down. The "not defined in the current scope" can be rephrased to "doesn't have access from the current scope", in which case it should be transferred from within MyFunc (or main) as a value, either by boost::function of by another means with inheritance.
Asaf
Fair enough; I wasn't sufficiently careful in my wording. My point is that C++ doesn't support true runtime binding, a consequence of which is that you can't invoke something that is completely unknown. There is nothing magic about functors. foo is completely unknown outside of main(). Any solution, be it inheritance or whatever, has to make the essence of foo (its public executable interface) accessible outside of main(), and it has to do so at compile time. COM is perhaps the most elaborate example.
Conal
+1  A: 

function local classes cannot be used as template arguments if that's what you mean. This will only be supported by C++0x.

sellibitze
+1  A: 

It appears possible to use the address of a static function of a local class. However, operator() must be a non-static member function, hence you'll need to give it a name:

#include <iostream>

template <class T>
void bar(T f)
{
    f();
}

int main()
{
    class foo {
        public:
        static void do_it() {
            std::cout << "Hello" << std::endl;
        }
    };
    bar(&foo::do_it);
    return 0;
}
UncleBens