I have this mechanics in my project. I need to call loop with any number of shared_ptr's of Behaviors and Listeners but can't seem to get it to work. If I input a list of Behaviors into loop(), it works. If I put in a list of Listeners, I need to comment out line 28 to make it to work. I need line 45 to work.
#include <cstdlib>
#include <memory>
#include <set>
usingnamespace std;
class Robot {
public:
Robot(){};
};
class Behavior {
public:
Behavior(Robot &o): r(o){};
Robot &r;
};
class Listener{
public:
Listener(){};
};
class MacroBehavior : public Behavior {
public:
MacroBehavior(Robot &o) : Behavior(o) {};
template <typename ...ArgsL, typename ...ArgsB> void loop( ArgsL... l_args, ArgsB... b_args ){
std::set<std::shared_ptr<Behavior> > behaviors {b_args...}; //comment out to get x->loop(l,m); working
std::set<std::shared_ptr<Listener> > listeners {l_args...};
}
};
int main(int argc, char** argv) {
Robot create;
std::shared_ptr<MacroBehavior> x= std::make_shared<MacroBehavior>(create);
std::shared_ptr<MacroBehavior> y= std::make_shared<MacroBehavior>(create);
std::shared_ptr<MacroBehavior> z= std::make_shared<MacroBehavior>(create);
std::shared_ptr<Listener> l= std::make_shared<Listener>();
std::shared_ptr<Listener> m= std::make_shared<Listener>();
x->loop(y,z); //input two MacroBehaviors OK
//x->loop(l,m); //only works if line 28 is commented out
//x->loop(y,z,l,m); //This is what I need to get working
return 0;
}
Thanks, I am using your solution. I used std::initializer_list in one of my class member functions before but I didn't like the extra curly brackets inside the () operator especially since all the parameters are of one type. I made the curly brackets go away with the use of Variadics. In this case though, using the curly brackets logically groups the different types of parameters. I am curious though, is there no way to use multiple parameter packs in a variadic function?
> I am curious though, is there no way to use multiple parameter packs in a variadic function?
Multiple parameter packs are allowed only if they can be deduced unambiguously.
... A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template ...
[Example:
1 2 3 4
// ...
// U can be neither deduced from the parameter-type-list nor specified
template<class... T, class... U> void f() {} // error
template<class... T, class U> void g() {} // error
—end example ] - IS
Two parameter packs, both at the top level:
1 2 3 4 5 6 7 8 9 10 11 12
#include <iostream>
template < typename... T, typename... U > void foo( T&&... , U&&... )
{
std::cout << "sizeof...(T): " << sizeof...(T) << " sizeof...(U): " << sizeof...(U) << '\n' ;
}
int main()
{
foo( 1, 'a', "hello", 7.85, std::cout, 7, 'x' ) ; // *** error: no matching function - candidate 'foo' is not viable (clang++, microsoft)
// g++ swallows this, with sizeof...(T): 0 sizeof...(U): 7
}
So basically, you can combine multiple parameter packs if one of the packs is wrapped in an object, a tuple in this case. And it seems, you can put in any number of objects in front of a parameter pack if those objects are declared in the function argument before the parameter pack. However, if they are put in after the parameter pack declaration, the parameter pack swallows the trailing objects and so the function signature cannot be matched.