In my last question I received great help in getting a template specialization to work. Now I need a little extension. I want two specializations for these statements:
int main()
{
// First specialization
holder_ext<person> h1;
holder_ext<person, &person::age> h2;
holder_ext<int> h3;
// Second specialization
holder_ext<person, &person::age, &person::name> h4;
}
My class person looks like this:
class person
{
private:
std::string name_;
int age_;
public:
person(const std::string &name)
: name_(name), age_(56)
{}
void age(int a) { age_ = i; }
void name(const std::string &n) { name_ = n; }
};
The special thing is, that the two member functions have different parameter types. So I can't use the same variadic template member function for both. I tried it with two different variadic templates. But that doesn't work. Also default values for the member functions do not work.
Does anybody have a good hint for me?
This is the solution with one member function (thanks to Pubby ):
template < class T, void (std::conditional<std::is_class<T>::value, T, struct dummy>::type::* ...FUNC)(int)> class holder;
template < class T, void (T::*FUNC)(int)>
class holder<T, FUNC>
{
public:
explicit holder() : setter(FUNC) { std::cout << "func\n"; }
private:
std::function<void (value_type&, int)> setter;
};
template < class T>
class holder<T>
{
public:
explicit holder() { std::cout << "plain\n"; }
};
Thanks again in advance!
PS: And no, I won't come up in two days with "what must do with three, four, five member functions"? ;-)
For a fully generic solution you would be hitting a problem that cannot be resolved: The type of non-type template argument cannot be inferred, so it must be explicit in the template declaration, so there is no way of telling the template that you want multiple pointer-to-member arguments each of which will have a yet unknown type.
I haven't played with C++11 enough, but you could try forcing an ordering on the member template arguments and provide all signatures in the template:
template <typename T,
void (std::conditional<...>::type*)(int),
void (std::conditional<...>::type*)(const std::string&)>
Again, it might work or it might not...
Finally I found a solution for my problem. It is a mix between variadic templates and template specilization:
template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int) = nullptr,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::* ...FUNC2)(const std::string&)
>
class holder_ext;
template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int),
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC2)(const std::string&)
>
class holder_ext<T, FUNC1, FUNC2>
{
public:
holder_ext() { std::cout << "func 2 test\n"; }
};
template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int)
>
class holder_ext<T, FUNC1>
{
public:
holder_ext() { std::cout << "func 1 test\n"; }
};
I use a not implemented declaration and define two specializations. One with both member function and the other one for all other cases.
If there is a better solution dont't hesitate to tell me.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.