Specialize a template for void parameter - c++

I have a the following template and specialization (this code is not correct, but hopefully demonstrates my intent well enough):
template <typename T> widget &&make_widget(T &&val) { // (1)
return std::move(widget(std::forward<T>(val)));
}
template <> widget &&make_widget(void) { // (2)
return std::move(widget());
}
The intent is to have a factory function that can be called like this:
make_widget(arbitrary_function());
And have it choose the default constructor if arbitrary_function returns void.
However, with clang 3.7 I get the following error:
error: no function template matches function template specialization 'make_widget'
pointing to the line of (2). How can I implement this correctly?

You can't do this. It's impossible to create a function that has a parameter of type void. What you can do is make the function variadic, like make_unique.
template <typename... T>
widget make_widget(T&&... val) {
return widget(std::forward<T>(val)...);
}
Then if you want to do something like
auto w = make_widget(void_function());
there is nothing stopping you from just doing instead:
void_function();
auto w = make_widget();
or even, if you really need it to be one statement for some reason,
auto w = (void_function(), make_widget());
Three further notes:
You should nix the std::move in the return statement since the result of calling the constructor is already an rvalue.
Never return a reference (even rvalue reference) to a temporary! It will always become a dangling reference.
There is no point to the make_widget function if forwarding its arguments to the widget constructor is the only thing it does. Note that make_unique takes care of calling new for you, and that make_tuple deduces the template arguments for the tuple itself. Your make_widget function doesn't do anything like that.

As it's been pointed out, the problem is not really in the template specialization, but the usage of a void expression.
I can, however, suggest an alternative syntax that uses an intermediate lambda, and a helper template, to achieve the same results at a cost of a little bit of negligible extra usage syntax.
#include <functional>
class widget {
public:
widget();
widget(int);
};
template <typename T> widget &&do_make_widget(T &&val) { // (1)
return std::move(widget(std::forward<T>(val)));
}
widget &&do_make_widget() { // (2)
return std::move(widget());
}
template <typename T>
class do_make_widget_invoke {
public:
template<typename functor_type>
static auto invoke(functor_type &&functor)
{
return do_make_widget(functor());
}
};
template <>
class do_make_widget_invoke<void> {
public:
template<typename functor_type>
static auto invoke(functor_type &&functor)
{
functor();
return do_make_widget();
}
};
template<typename functor_type>
auto make_widget(functor_type &&functor)
{
return do_make_widget_invoke<decltype(functor())>
::invoke(std::forward<functor_type>(functor));
}
Testing the above with g++ 5.1.1 in -std=c++14 mode, I seem to get the right results with the following syntax, which is pretty much what you're trying to accomplish:
int foobar()
{
return 0;
}
int main()
{
make_widget([]{ return foobar(); });
}
and:
void foobar()
{
}
int main()
{
make_widget([]{ return foobar(); });
}

Related

Extract type of input parameter in templated function taking a function as parameter

I have this function:
template<typename T, int (*F)(T&)>
void DoStuff(T& s)
{
auto an = make_any<T>(s);
cout << _GetDataFromAny<MyStruct, F>(an);
}
Which needs to be called like this:
DoStuff<MyStruct, Fun>(s);
This works fine, however I don't like having to specify the first type, since it is part of the signature of the second parameter. I would like to be able to deduce it such that I can just call:
DoStuff<Fun>(s);
However, I don't know how to specify in the template that the type T needs to be deduced from the signature of the function F.
Is this possible?
You can write a helper that deduces the argument type of a function pointer that returns int:
template<typename T>
T arg_type(int(*)(T&));
and then rewrite your function template slightly to take in a function pointer as a non-type template parameter, and figure out the argument type from that
template<auto F, typename T = decltype(arg_type(F))>
void DoStuff(T& s) {
// ...
}
Disclaimer: This answer went through a series of edits and corrections, many thanks goes to Jarod42 for his patience and help, and cigien for fruitful discussion. It is a bit longer than necessary, but I felt it is worth to keep a bit of the history. It is: the most simple / the one I would prefer / some explanation of the previous confusion. For a quick answer, read the second part.
The simple
You can use an auto template parameter (since C++17) for the function pointer and let T be deduced from the argument:
template<auto F, typename T>
void DoStuff(T& s)
{
int x = F(s);
}
int foo(double&){ return 42;}
int main() {
double x;
DoStuff<&foo>(x);
}
Live Demo
The "right"
The downside of the above is that F and T are "independent". You can call DoStuff<&foo>(y) with eg a std::string y; and instantiation will only fail when calling F. This might lead to a unnecessarily complex error message, depending on what you actually do with F and s. To trigger the error already at the call site when a wrong T is passed to a DoStuff<F> you can use a trait to deduce the argument type of F and directly use that as argument type of DoStuff:
template <typename T> struct param_type;
template <typename R,typename P>
struct param_type< R(*)(P&)> {
using type = P;
};
template<auto F>
void DoStuff(typename param_type<decltype(F)>::type& s)
{
int x = F(s); // (1)
}
int foo(double&){ return 42;}
int main() {
double x;
DoStuff<foo>(x);
std::string y;
DoStuff<foo>(y); // (2) error
}
Now the error that before would only happen inside the template (1) happens already in main (2) and the error message is much cleaner.
Live Demo
The "wrong"
Mainly as curiosity, consider this way of deducing the parameter type from the function pointer:
template <typename T> struct param_type;
template <typename R,typename P>
struct param_type< R(*)(P&)> {
using type = P;
};
template<auto F, typename T = typename param_type<decltype(F)>::type>
void DoStuffX(T& s)
{
}
int foo(double&){ return 42;}
int main() {
double x;
DoStuffX<foo>(x);
}
This was my original answer, but it was not actually doing what I thought it was doing. Note that I was not actually calling F in DoStuff and to my surprise this compiled:
int main() {
std::string x;
DoStuffX<foo>(x);
}
The reason is that the default template argument is not used when T can be decuded from the passed parameter (see here). That is, DoStuffX<foo>(x); actually instantiates DoStuffX<foo,std::string>. We can still get our hands on the default via:
int main() {
std::string x;
auto f_ptr = &DoStuffX<foo>;
f_ptr(x); // error
}
Now calling DoStuffX<foo> with a std::string is a compiler error, because here DoStuffX<foo> is instantiated as DoStuffX<foo,double>, the default argument is used (there is no parameter that could be used to deduce T when DoStuffX is instantiated).

pass lambda to function that accepts function with templated types

I'm attempting to make a template function that takes a function as a parameter and the parameter function has arguments for the template to deduce.
Example time:
Here is a function that accepts a fixed function type and works
void func_a(void(*func)(int)) {
func(1);
}
int main() {
auto f = [](int x) -> void { printf("%i\n", x); };
func_a(f);
return 0;
}
Here is what I want to do, expanding on the first example (this won't compile)
template <typename... T>
void func_b(void(*func)(T...)) {
func(1);
}
int main() {
auto f = [](int x) -> void { printf("%i\n", x); };
func_b(f); // neither of
func_b<int>(f); // these work
return 0;
}
Ideally I'd like func_b to accept both a regular function and a lambda function like func_a does, but with template magics.
Unfortunately, template deduction doesn't work well with implicit conversions. However, you can convert the lambda explicitly into a function pointer type. The shortest, but somewhat confusing way to do that is to apply unary + operator:
func_b(+f);
Or you could use the more intuitive, but also verbose and DRY-violating cast operation:
func_b(static_cast<void(*)(int)>(f));
But perhaps, you'll want to simply accept any callable type, instead of only function pointers:
template <class Fun>
void func_c(Fun&& func) {
func(1);
}
This works fine with lambdas. No conversions involved.
func_c(f);
And it also works for capturing lambdas (that cannot be converted to function pointers), std::function and function objects such as those defined in <functional>.
here you have some options that work:
#include <functional>
template <typename T>
void func_b(T&& func) {
func(1);
}
template <typename... T>
void func_c(std::function<void(T...)> func) {
func(1);
}
template <typename... T>
void func_d1(std::function<void(T...)> func) {
func(1);
}
template<typename... Params>
using fun = std::function<void(Params...)>;
template <typename T, typename... P>
void func_d(T& func) {
func_d1(fun<P...>(func));
}
int main() {
auto f = [](int x) { printf("%i\n", x); };
func_b(f);
func_b(std::function<void(int)>(f));
func_c(std::function<void(int)>(f));
func_d<decltype(f),int>(f);
return 0;
}
The issue is: A lambda is not a function pointer or std::function-object.
func_b uses perfect forwarding so T will be the type of the lambda not a std::function object.
For func_c. You should not convert a lambda to a c-style function pointer. A std::function object is able to do this conversion but only explicitly (by design) so you need to explicitly convert them.
func_d (and func_d1) combine the other aspects. It forwards the lambda and makes a std::function-object explicitly out of it though it needs an additional template parameter.

Template class overload std::bind a member fucntion

Somebody can help me to build this source code in a right way,
I understand that I shold declare the callBack as std::function<void(std::unique_ptr<int>&& param)> because this take a no copy
constructible param(std::unique_ptr), so what is the correct type if I no use auto to deduce the type?
#include <functional>
#include <memory>
template <class T>
class SomeClass {
void someFunctionCallback(float o) = 0;
};
template <>
class SomeClass<float> {
public:
SomeClass() = default;
inline void someFunction() {
// std::function<void()>
auto callBack {
std::move(std::bind(&SomeClass<float>::someFunctionCallback,
this,
std::unique_ptr<int>{new int(9)}))};
useCallBack(std::move(callBack));
}
inline void someFunctionCallback(std::unique_ptr<int>&& param) {
}
inline void useCallBack(std::function<void()> &&callBack) {
// callBack();
}
};
int main() {
SomeClass<float> k;
k.someFunction();
return 0;
}
Your code has a couple of problems. First, auto { ... } will deduce an std::initializer_list. That's not what you want. Use a brace-or-equal initializer instead.
auto callBack =
std::bind(&SomeClass<float>::someFunctionCallback,
this,
std::unique_ptr<int>{new int(9)});
Second, your function takes an rvalue-reference, but std::bind will pass an lvalue. Read Passing rvalues through std::bind for a full explanation, but as a workaround you can use this ugly cast:
using uptr = std::unique_ptr<int>;
auto callBack =
std::bind(&SomeClass<float>::someFunctionCallback,
this,
std::bind(static_cast<uptr&&(&)(uptr&)>(std::move<uptr&>),
std::unique_ptr<int>{new int(9)})
) ;
Finally, just make your function a template. The whole idea is not to worry about the type, and auto follows the rules of template argument deduction anyway.
template <typename T>
inline void useCallBack(T callBack) {
callBack();
}

Need clarification on C++ template format

I'm going through some template sample code and there's one thing I don't get.
Take a template methode:
template<class Seq, class T, class R>
void apply(Seq &sq, R(T::*f)() const) {
typename Seq::iterator it = sq.begin();
while(sq.end() != it) {
((*it++)->*f)();
}
}
A sample class:
class MyClass {
public:
MyClass() {}
void doSomething() const {
std::cout << "doing stuff..." << std::endl;
}
};
And the test code:
void testMyClass() {
vector<MyClass*> v;
for(size_t i = 0; i < 5; ++i) {
v.push_back(new MyClass());
}
// call a member methode on all elements in container
apply(v, &MyClass::doSomething);
}
I would be grateful if someone could explain me what is that class R for, as defined in the template definition?
class R refers to the return type of the function pointer being passed to the function apply. It is automatically deduced from the actually passed function pointer type, so you never really need to care about it when calling apply.
The implementation of apply discards the return value of the function, so you could simply force the passed function to return void:
template<class Seq, class T>
void apply(Seq &sq, void(T::*f)() const) {
typename Seq::iterator it = sq.begin();
while(sq.end() != it) {
((*it++)->*f)();
}
}
However, now you restrict the call site to only pass such function pointers. Sadly, a pointer to a function which returns something isn't implcitly convertible to one which doesn't, although it would be pretty "intuitive".
So when you take a function pointer as an argument, and you don't care about the return type, it's better to accept "any" return type than "none".
class R in the template is used to deduce the return type of the function. In your case, it is deduced to be of type void.

template argument deduction for pointer to member function?

I am trying to build a statically bound delegate class, where the member function is bound at compile time, thereby aiding optimisation.
I have the following code which works exactly how I want it to:
#include <iostream>
namespace thr {
template<typename T, T func>
struct delegate;
template<typename R,
typename C,
typename... A,
R (C::* mem_fun)(A...)>
struct delegate<R(C::*)(A...), mem_fun>
{
delegate(C* obj_)
: _obj(obj_)
{}
R operator()(A... a)
{
return (_obj->*mem_fun)(a...);
}
private:
C* _obj;
};
} // namespace thr
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;
cb c(&f);
std::cout << c(4, 3);
return 0;
}
However, the usage is not very elegant:
thr::delegate<decltype(&foo::bar), &foo::bar>
I would like to use a function template which deduces the template parameters and returns a delegate instance; something along the lines of (this code does not compile):
template<typename C, typename T, T func>
thr::delegate<T, func> bind(T func, C* obj)
{
return thr::delegate<decltype(func), func>(obj);
}
This would allow for more elegant syntax:
auto cb = bind(&foo::bar, &f);
Is it possible to deduce a non-type parameter in a function template?
Is what I'm trying to achieve even possible?
Would std::function help? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function Your example looks quite close.
I think the compiler supplied STL does pretty horrible things to make it work smoothly. You may want to have a look at as an example before giving up.
Edit: I went out and tried what you try to accomplish. My conclusion is a compile error:
The return type of the bind (delegate) must name the pointer to member because it is your own requirement.
bind should accept the name of the pointer to member to be elegant (i.e. your requirement)
Compiler requires you to not shadow the template parameter with a function parameter or use the name in both parameters and return type.
Therefore one of your requirements must go.
Edit 2: I took the liberty of changing your delegate so bind works as you wish. bind might not be your priority though.
#include <iostream>
namespace thr {
template<typename C,typename R,typename... A>
struct delegate
{
private:
C* _obj;
R(C::*_f)(A...);
public:
delegate(C* obj_,R(C::*f)(A...))
: _obj(obj_),_f(f)
{}
R operator()(A... a)
{
return (_obj->*_f)(a...);
}
};
} // namespace thr
template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){
return thr::delegate<C,R,A...>(obj,f);
}
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
auto c = bind(&foo::bar, &f);
std::cout << c(4, 6);
return 0;
}
It is possible to deduce other entities than types in a function signature, but function parameters themselves cannot then be used as template parameters.
Given:
template <size_t I> struct Integral { static size_t const value = I; };
You can have:
template <size_t N>
Integral<N> foo(char const (&)[N]);
But you cannot have:
Integral<N> bar(size_t N);
In the former case, N as the size of the array is part of the type of the argument, in the latter case, N is the argument itself. It can be noticed that in the former case, N appeared in the template parameters list of the type signature.
Therefore, if indeed what you want is possible, the member pointer value would have to appear as part of the template parameter list of the function signature.
There may be a saving grace using constexpr, which can turn a regular value into a constant fit for template parameters:
constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); }
Integral<fib(4)> works;
But I am not savvy enough to go down that road...
I do however have a simple question: why do you think this will speed things up ? Compilers are very good at constant propagation and inlining, to the point of being able to inline calls to virtual functions when they can assess the dynamic type of variables at compilation. Are you sure it's worth sweating over this ?