How to compare templated class with variadics?

I've this variadic template class implementation:

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
33
34
35
36
37
38
39
40
41
42
43
// Predefine template delegate factory
template < typename R, typename... Args > 
class brGenericDelegate ;

// C++11 template alias to announce functor definition
template < typename R, typename... Args > 
using brGenericDelegateType = std::function< std::shared_ptr<R>(Args...) > ;

class brDelegate
{
protected:
	brDelegate(){}
	
public:
    virtual ~brDelegate() = default ;
		
    template < typename R, typename... Args >
    static std::shared_ptr<brDelegate> create( typename brGenericDelegate<R,Args...>::functor func ) 
	{ 
		return std::make_shared<brGenericDelegate<R,Args...>>(func) ; 
	}


    template < typename R, typename... Args > 
	std::shared_ptr<R> run( Args... args ) const
    {
        using derived_type = brGenericDelegate<R,Args...> ;
        return dynamic_cast< const derived_type& >(*this)(args...) ;
    }		
};

template < typename R, typename... Args > 
class brGenericDelegate : public brDelegate
{
public:
    using functor = brGenericDelegateType< R, Args... >;
    brGenericDelegate( functor f ) : fn(f) {}
		
    std::shared_ptr<R> operator() ( Args... args ) const { return fn(args...) ; }
		
private:
    const functor fn ;
};


This template works fine for me. Now I have to compare, if the functors of the generic templates are equals ore not. Actually I see no way to reach this aim, because I've to cast the brDelegate on each request. Any idea how I could reach this aim?
I may not have understood the problem in its entirety.

Can't we compare types with std::function<>::target_type()
http://en.cppreference.com/w/cpp/utility/functional/function/target_type

and values with std::function<>::target<>()
http://en.cppreference.com/w/cpp/utility/functional/function/target
Sorry for my bad question description. I want to figure out a way to check if two brDelegates I've are equals in their target type and arguments, i.e.:

1
2
3
4
5
6
7
8
9
auto d1 = brDelegate::create<User>([] () -> std::shared_ptr<User> { return std::make_shared<User>(); }); 

auto d2 =  brDelegate::create<IUser, int>([] (int age) -> std::shared_ptr<IUser> { return std::make_shared<User>("Klaus", age); });

auto d3 = brDelegate::create<IUser, int>([] (int age) -> std::shared_ptr<IUser> { return std::make_shared<User>("Klaus", age); });

// I would test in some way
d1 == d2 ?   --> should result in false
d2 == d3 ?   --> should result in true


Based on your hint I've added an virtual method to brDelegate which returns the type_index of the std::function<>::target type. But this doesn't work, the requested type index is different on each functor, also on d2 and d3 ..


Found: brDelegateTest_processDelegates_Test::TestBody()::{lambda(int)#5}
Found: brDelegateTest_processDelegates_Test::TestBody()::{lambda(int)#6}


Meanwhile I got an approach:

I could determine the std::type_index of the functor return value on initialization. Also the size of the ARGS and maybe determine their types by parameter unpacking. Then I could check those values at brDelegate compare operator.

Or is this a bad idea and I should better use some different way?

Last edited on
Something like this?

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <functional>
#include <memory>

// Predefine template delegate factory
template < typename R, typename... Args >
class brGenericDelegate ;

// C++11 template alias to announce functor definition
template < typename R, typename... Args >
using brGenericDelegateType = std::function< std::shared_ptr<R>(Args...) > ;

class brDelegate
{
protected:
    brDelegate(){}

public:
    virtual ~brDelegate() = default ;
    virtual bool operator== ( const brDelegate& that ) const { return typeid(*this) == typeid(that) ; }
    virtual bool operator!= ( const brDelegate& that ) const { return !( *this == that ) ; }

    template < typename R, typename... Args >
    static std::shared_ptr<brDelegate> create( typename brGenericDelegate<R,Args...>::functor func )
	{
		return std::make_shared<brGenericDelegate<R,Args...>>(func) ;
	}


    template < typename R, typename... Args >
	std::shared_ptr<R> run( Args... args ) const
    {
        using derived_type = brGenericDelegate<R,Args...> ;
        return dynamic_cast< const derived_type& >(*this)(args...) ;
    }
};

bool operator== ( const std::shared_ptr<brDelegate>& a, std::shared_ptr<brDelegate>& b )
{
    if( a && b ) return *a == *b ;
    else return !a && !b ;
}

bool operator!= ( const std::shared_ptr<brDelegate>& a, std::shared_ptr<brDelegate>& b ) { return !( a == b ) ; }

template < typename R, typename... Args >
class brGenericDelegate : public brDelegate
{
public:
    using functor = brGenericDelegateType< R, Args... >;
    brGenericDelegate( functor f ) : fn(f) {}

    std::shared_ptr<R> operator() ( Args... args ) const { return fn(args...) ; }

private:
    const functor fn ;
};

struct IUser { virtual ~IUser() = default ; };
struct User : IUser { User( const char* = nullptr, int = 0 ) {} };

int main()
{
    auto d1 = brDelegate::create<User>([] () -> std::shared_ptr<User> { return std::make_shared<User>(); });
    auto d2 =  brDelegate::create<IUser, int>([] (int age) -> std::shared_ptr<IUser> { return std::make_shared<User>("Klaus", age); });
    auto d3 = brDelegate::create<IUser, int>([] (int age) -> std::shared_ptr<IUser> { return std::make_shared<User>("Klaus", age); });

    std::cout << std::boolalpha << ( d1 == d2 ) << '\n' // false
              << ( d2 == d3 ) << '\n' ; // true

}

http://coliru.stacked-crooked.com/a/27df287d82ba3be6

Danger: we have violated the principle of least surprise by redefining the semantics of equality comparison of pointers.
Prefer using a named operation instead. For instance,
bool brDelegate::are_of_the_same_derived_type( const brDelegate& that ) const ;
Thanks for the hit to the back of my head ;) I was too fixed to compare the functors, that I've overseen this simple solution!
Last edited on
Topic archived. No new replies allowed.