samedi 31 janvier 2015

Default value for function argument which is pointer to member

I'm trying to implement decorator for functions using variadic templates. And try to minimize number of overloads since it reduce the size of a compiler error messages in case of template params deducion failure. I have implementation which works with any member of any class (works with delegate Ret (Ctx::*member)(Args...)) and one extra overload which do not take pointer to member function and just calls first version passing &Ctx::opeator(). I've tried to remove extra overload by adding default value for member pointer argument here. Here is the version which compiles:



template<
typename Decorator,
typename Ctx, typename R, typename... Args,
typename... CTorArgs
>
Decorator decorate(
CTorArgs&&...cargs,
const Ctx &obj, R (Ctx::*member)(Args...) const = &Ctx::operator()
) {
return Decorator(
std::function<R(Args...)>([&obj, member](Args... args){
return (obj.*member)(args...);
}),
std::forward(cargs)...
);
}


But it can't be called without explicit member function specification. Here is an example I'm playing with right now:



struct IntDecorator {
IntDecorator(std::function<std::string(std::string)> func):
m_func(func) {}

std::string operator() (int val) {
std::ostringstream oss;
oss << val;
return m_func(oss.str());
}
private:
std::function<std::string(std::string)> m_func;
};

struct PrefixAdder {
PrefixAdder(std::string prefix): m_prefix(prefix) {}
std::string addPrefix(std::string val) const {return m_prefix + val;}
std::string operator() (std::string val) const {return m_prefix + val;}
private:
std::string m_prefix;
};

int main(int, char**) {
PrefixAdder p("+++> ");
std::cout << decorate<IntDecorator>(p, &PrefixAdder::addPrefix)(123) << std::endl;
std::cout << decorate<IntDecorator>(p, &PrefixAdder::operator())(123) << std::endl;
std::cout << decorate<IntDecorator>(p)(123) << std::endl; // compilation error
}


compiler can't deduce type R (member function return type). The code works after adding extra overload which I try to elliminate or by specifying all template parameters which is even worse than extra overload:



template<typename Decorator, typename Ctx, typename... CTorArgs>
Decorator decorate(CTorArgs&&...cargs, const Ctx &obj) {
return decorate<Decorator>(cargs..., obj, &Ctx::operator());
}


Can I have automatic type dedution without additional version of decorate template? What is the problem to deduce types automatically here in C++11?


Aucun commentaire:

Enregistrer un commentaire