my new Event class: template variadics and how test a valid function\lambda

Pages: 12
Jun 22, 2016 at 9:38am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <functional>

template < typename... ARGS > struct event
{
    event() = default ;
    template < typename FN > event( FN fn ) : callback(fn) {} // converting constructor

    const event& operator() ( ARGS... args ) const { if(callback) callback(args...) ; return *this ; }

    private: std::function< void( ARGS... ) > callback = nullptr ;
};

struct timer
{
    template < typename FN > timer( FN fn ) : timer_callback(fn) {} // converting constructor

    void test() const { std::cout << "*** test *** timer - " ; timer_callback() ; } // only for exposition

    // ...

    private: event<> timer_callback ;
};

int main()
{
    const event<int> test_event( []( int arg ) { std::cout << "*** test **** event<int> - arg == " << arg << '\n' ; } ) ;
    test_event(99) ;

    timer my_timer( [] { std::cout << "tick!\n" ; } ) ;
    my_timer.test() ;
}

http://coliru.stacked-crooked.com/a/0e3be77a36d586d1
http://rextester.com/SWSEF12194
Jun 22, 2016 at 7:13pm
JLBorges: why the test_event() it's const?
Coder777: is there anyway for be Implicit?
thanks to all
Jun 22, 2016 at 7:23pm
> why the test_event() it's const?

Force of habit; if something can be declared const, declare it as const.
For the rationale, see: http://www.cplusplus.com/forum/beginner/180986/#msg888218

EDIT: In this toy snippet, my_timer could also be a const object, though a real life timer object is unlikely to be a const object.
Last edited on Jun 22, 2016 at 7:28pm
Jun 22, 2016 at 7:32pm
like i know: if test_event it's const, i can't edit after the 1st time(constructor).
but thanks for all... thank you
Jun 23, 2016 at 7:52am
is there anyway for be Implicit?
What do you mean by 'Implicit'? If you want to pass both Event and the lambda to Timer use the constructor JLBorges showed on line 16.
Jun 24, 2016 at 8:26pm
JLBorges: see that i'm trying overloading the operator '=':
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template < typename... ARGS > struct Event2
{
public:
    Event2() = default ;
    template < typename FN > Event2( FN fn ) : callback(fn) {} // converting constructor

    const Event2& operator() ( ARGS... args ) const { if(callback) callback(args...) ; return *this ; }

    bool IsValid()
    {
        if (callback)
            return true;
        else
            return false;
    }

    Event2 &operator =(std::function<void(ARGS... args)> Event)
    {
        callback=Event;
    }

    private: std::function< void( ARGS... ) > callback = nullptr ;
};

when i use it:
1
2
3
4
5
6
7
8
9
10
11
12
13
Event2<int, int> test{[](int a, int b)
{
    MessageBox("hello world 1: " + to_string(a+b));
}};

//overloading operator '=':
 test(3,4);//works
        test=[](int a, int b)
        {
            MessageBox("hello world 2: " + to_string(a*b));

        };
        test(4,5);

error message:
- ambiguous overload for 'operator=' (operand types are 'Event2<int, int>' and 'WinMain(HINSTANCE, HINSTANCE, LPSTR, int)::__lambda222::__lambda239');

Cadidates are:
Event2<ARGS>& Event2<ARGS>::operator=(std::function<void(a ...)>) [with ARGS = {int, int}]

what i'm doing wrong?
Jun 25, 2016 at 12:57am
clang++ emits an easy to understand diagnostic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <functional>

template < typename... ARGS > struct Event2
{
public:
    Event2() = default ;
    template < typename FN > Event2( FN fn ) : callback(fn) {} // converting constructor

    const Event2& operator() ( ARGS... args ) const { if(callback) callback(args...) ; return *this ; }

    bool IsValid()
    {
        if (callback)
            return true;
        else
            return false;
    }

    Event2 &operator = ( std::function<void(ARGS... args)> Event ) { callback = Event ; return *this ; }

    private: std::function< void( ARGS... ) > callback = nullptr ;
};

int main()
{
    Event2<int, int> test{ [] (int a, int b) { std::cout << "1. " << a+b << '\n' ; } };
    test(3,4);//works

    test = [] (int a, int b) { std::cout << "2. " << a*b << '\n' ; } ; // *** error
    test(4,5);
}

main.cpp:30:10: error: use of overloaded operator '=' is ambiguous ...

main.cpp:4:38: note: candidate is the implicit move assignment operator
main.cpp:4:38: note: candidate is the implicit copy assignment operator
main.cpp:20:13: note: candidate function Event2 &operator = ( std::function<void(ARGS... args)> Event ) ...

http://coliru.stacked-crooked.com/a/231e61a33d4c81a1

Since the constructor is a converting constructor, the simplest solution is to remove the custom assignment operator (then there would be no ambiguity; the implicitly declared move assignment operator would be selected).
http://coliru.stacked-crooked.com/a/d16050e414ca81fd
Topic archived. No new replies allowed.
Pages: 12