How to convert a constructor to a std::function [duplicate] - c++

This question already has answers here:
How to pass a function pointer that points to constructor?
(8 answers)
Construct std::function with a constructor based on template
(1 answer)
Closed 3 years ago.
Is there any way to assign a constructor to a function like 'f':
struct C
{
C(int){};
};
auto f = C::C(int); // not work
auto g = [](int){ return C(int()); }; // works
Neither C, C::C, &C, &C::C, C::&C, C::C(int), &C::C(int) ... works
Solution proposed by Friday Pie:
template <class T>
struct ConstructHelper
{
template <class... Args>
static T&& construct(Args&&... args)
{
return std::move(T(std::forward<Args>(args)...));
}
};
auto f = ConstructHelper<C>::construct<int>; // works
auto c = apply(f, 0); // works

The code you tried to write follows other rules than than the lambda that you wrote.
In the first one, you are trying to get a pointer to a member function: &C::C This would be similar to &C::print (assuming argument int) The first argument of this function would be a pointer to C, the second would the the int.
However, we are trying to do this for the constructor. So we don't have a valid C to work on. The result is that this simply doesn't compile.
Note that if you do want to execute a constructor on existing memory, you need placement new.
Your second code is a lambda. In short: a class with operator() implemented. And in this operator, you write code as in any other function and return a newly constructed instance by value. (Although, this looks a lot like a vexing parse) Tis is similar to executing the print function that was mentioned before.
So both would have different semantics and your compiler is right in failing to compile this code.

In theory your hypothetical function apply would look quite simple as a template
#include <iostream>
#include <type_traits>
struct C
{
C(int){};
};
template <class F, class... Args>
auto apply ( F&& f, Args&&... args) -> typename std::result_of<F(Args...)>::type
{
return f(args...);
}
float foo (int a, float b) { return a*b; }
int main()
{
auto b = apply(&foo, 3, 5.f);
//auto b = apply(&C::C, 3); //error: taking address of constructor 'C::C'
return 0;
}
But it is impossible to take address of constructor, as per the ISO standard. In most cases this special function is a non-entity in resulting code.
Neither explicit call to constructor is allowed. Your lambda function does thing differently. It constructs an object of class C as to per defined effect of that expression.
You could use a bogus argument and SFINAE
template <class F, class... Args>
auto apply ( F&& f, Args&&... args)
-> std::enable_if_t<std::is_invocable<F, Args...>::value,
typename std::result_of<F(Args...)>::type>
{
return f(args...);
}
template <class T, class... Args>
auto apply ( T&&, Args&&... args)
-> std::enable_if_t<!std::is_invocable<T, Args...>::value,T&&>
{
return std::move(T(args...));
}
but it's preferable to avoid that and rethink whatever meta-programming pattern you have in mind, i.e. avoid attempt to call same template name for different kinds of arguments, or make amends with lambda use. E.g. you may avoid to call apply() by using SFINAE.

Related

Variadic Function That Calls Constructor With Given Arguments

Need to create variadic template<T> function with different arg types that will call constructor of T with given arguments, sort of like when creating a thread but reverse (when creating a thread, its constructor calls function at given funct pointer).
So in pseudo code it should look something like this
template<typename T>
T* CreateNew( ARGS ) {
return new T( ARGS ); //Constructor Gets Same Arguments That Were
} //Passed To The Function
Want this to behave like when creating threads, when they call functions with their arguments that are of different types (which I am unsure how to achive).
Its not entirely clear to me but I think you want to look up variadic templates, e.g.:
template <typename T, typename... Args>
T* CreateNew(Args... args) {
return new T(args...);
}
Adding Example:
#include <iostream>
class A {
public:
A(int a){
std::cout<<__PRETTY_FUNCTION__<<std::endl;
}
A(std::string a){
std::cout<<__PRETTY_FUNCTION__<<std::endl;
}
A(int a,std::string b){
std::cout<<__PRETTY_FUNCTION__<<std::endl;
}
};
template<typename T, typename... Args>
T* create(Args... args){
return new T(args...);
}
int main(){
A b(1);
A c("a");
A d(1,"a");
A* bp = create<A>(1);
A* cp = create<A>("a");
A* dp = create<A>(1,"a");
// This code leaks
return 0;
}
Note that because the changes are kept as minimal as possible, we still return a T* here as the original code. Most of the time, this is not a good idea since ownership is passed via raw pointers. Therefore, as suggested by the comments, you might want to use a std::unique_ptr, which would make your CreateNew function basically equivalent to std::make_unique.
The correct way to write this function is
template <typename T, typename... Args>
T* CreateNew(Args&&... args) {
return new T(std::forward<Args>(args)...);
}
Without the forwarding reference Args&& and without std::forward, the original value categories of the passed arguments will not be propagated to T's constructor, causing potential performance and semantic problems.

How to use std::function using variadic template

There is a template for constructing std::function:
template< class R, class... Args >
class function<R(Args...)>;
I have not figured out how to invoke it. (VC++, if that matters.)
Question: How can I use std::function with a variadic list without using std::bind?
#include <functional>
#include <iostream>
using vfunc = std::function<void()>;
using namespace std; // I know, I know.
template<class F, class... Args>
void
run(F&& f, Args&&... args) {
vfunc fn = bind(forward<F>(f), forward<Args>(args)...); //OK
//vfunc fn = vfunc(forward<F>(f), forward<Args>(args)...); // COMPILER ERROR
fn();
}
void foo(int x) {
cout << x << " skidoo\n";
}
int main() {
run(foo, 23);
return 0;
}
There is a template for constructing std::function.
template< class R, class... Args >
class function<R(Args...)>;
That's not what that declaration means. It's not declaring a constructor or a "template for constructing" anything; it's a specialization for the template class std::function. The specialization is the only definition of std::function; the base template is never defined. I think the point of this has something to do with using a function signature in the template declaration. That is, being able to use the template via function rather than as function.
You want to take a callable object and some number of values and create a new callable object that stores those values, which has an operator() overload that calls the given function with those values. std::function does not do that; it has no constructors for doing so.
This is exactly what std::bind is for. Basically, your code is fine as is: storing the result of bind within function is entirely valid.
In that case, you can just wrap the function in a lambda and construct your std::function from it.
template<class F, class... Args>
void run(F&& f, Args&&... args) {
auto fn = vfunc{
[=]() mutable {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
};
fn(); // fn is of type std::function<void()>
}
I made the lambda mutable so std::forward will not silently not move.
Note however that the [=] capture will copy everything. To support move only types, you can use a tuple:
[f = std::forward<F>(f), args = std::tuple{std::forward<Args>(args)...}]() mutable {
std::apply(std::forward<F>(f), std::move(args));
}
In C++20, this becomes easier:
[f = std::forward<F>(f), ...args = std::forward<Args>(args)...]() mutable {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}

Perfect forwarding with a temporary function wrapper

Consider the following code in C++14, following the posts here, here and here:
// Include
#include <tuple>
#include <iostream>
#include <type_traits>
// Temporary function queue declaration
template <class... F>
class temporary_function_queue;
// Apply function queue declaration
template <class... F>
constexpr temporary_function_queue<F&&...> apply_function_queue(F&&... f);
// Temporary function queue definition
template <class... F>
class temporary_function_queue final
{
// Types
private:
using const_lvalue_reference = const temporary_function_queue&;
using rvalue_reference = temporary_function_queue&&;
using temporary_type = temporary_function_queue<F&&...>;
using data_type = std::tuple<F&&...>;
// Lifecycle
private:
temporary_function_queue(rvalue_reference) = default;
temporary_function_queue(const_lvalue_reference) = delete;
temporary_function_queue operator=(rvalue_reference) = delete;
temporary_function_queue operator=(const_lvalue_reference) = delete;
explicit constexpr temporary_function_queue(F&&... f)
: _f{std::forward<F>(f)...}
{
}
// Temporary creator
public:
friend constexpr temporary_type apply_function_queue<>(F&&... f);
// Apply function queue declaration
public:
template <class... Args>
decltype(auto) operator()(Args&&... args) const&&
{
// Do I need to do std::forward on f0 too? If so, how?
return std::get<0>(_f)(std::forward<Args>(args)...);
}
// Data members
private:
data_type _f;
};
// Apply function queue definition
template <class... F>
constexpr temporary_function_queue<F&&...> apply_function_queue(F&&... f)
{
return temporary_function_queue<F&&...>(std::forward<F>(f)...);
}
/* Example of use
int main(int argc, char* argv[])
{
apply_function_queue(
[](auto i){std::cout<<0<<std::endl;},
[](auto i){std::cout<<1<<std::endl;}
)(0);
return 0;
}
*/
The goal is to produce the following call syntax:
apply_function_queue(f0, f1, f2)(a, b, c, d, e);
Where f0, f1, f2 are either function pointers, functors, lambdas..., and where a, b, c, d, e are arguments to be perfectly forwarded. This function should produce a temporary type, and then call the operator() of that temporary type, and this operator should do a perfect forwarding of fn (for now f0, it will be changed later) with the arguments a, b, c, d, e.... The temporary_function_queue should not be usable in any other context.
The problem is that I am a little lost with the forwarding, universal references and lvalue references... Is the code shown above safe? If not what example of use would lead to undefined behaviour? And in that case, how to make it safe, and efficient (ideally, I would like no runtime overhead on most compilers with -O3)?
Note: Dangling references are quite likely to happen with this approach.
auto make_f(); // return by value
auto&& q = apply_function_queue(make_f());
// q holds dangling rvalue reference
q(a, b, c); // whoops...
First some remarks about wording and deduction. Let:
template<class... T> void f(T&&... p) {}
Note: When this template is instantiated, there are two different packs here: T... and T&&....
Call it with an lvalue or type R and an rvalue of type Q:
R a;
f(a, Q{});
Now T... will be R&, Q but T&&... will be R&, Q&&.
Forwarding the pack p will result in the T&&... pack.
'decltype'(std::forward<T>(p)...) === T&&...
(Note: You can't actually apply decltype here - it's just for illustration.)
Therefore, I'll call the pack that is actually deduced (T...) the deduced types/pack and the result of adding rvalue references / forwarding (T&&...) the forwarded types/pack.
Applying && everywhere inside the class as well as in the return type of apply_function_queue is superfluous. (If you return temporary_function_queue<F&&...> from apply_function_queue there is no need for && inside temporary_function_queue. And if you apply && inside the class everywhere there is no need to return temporary_function_queue<F&&...>.)
You either instantiate the class template with the deduced pack and add && everywhere you want references our you instantiate the class template with the forwarding pack and don't add &&.
It is required to have the deduced types available in the class. (Because the friend declaration uses both F... and F&&....) So you'll want to remove && from the return type of apply_function_queue.
You'll need to change some declarations:
apply_function_queue
forward declaration:
template <class... F>
constexpr temporary_function_queue<F...> apply_function_queue(F&&... f);
definition:
template <class... F>
constexpr temporary_function_queue<F...> apply_function_queue(F&&... f)
{
return temporary_function_queue<F...>(std::forward<F>(f)...);
}
temporary_type
The class instance type is temporary_function_queue<F...> not temporary_function_queue<F&&...>!
using temporary_type = temporary_function_queue<F...>;
friend declaration
friend constexpr temporary_type apply_function_queue<F...>(F&&... f);
If you want perfect forwarding of rvalue function types in the function call operator you'll have to resort to manual casting / forwarding I think.
Inside decltype(auto) operator()(Args&&... args) const&& you'll find that
decltype(std::get<0>(_f)) === std::tuple_element_t<0u, data_type>&
which by reference collapsing rules is a lvalue reference. What you actually want, in order to forward the elements from the tuple is the tuple_element::type.
Thus you'd have to directly cast to the actual type in the tuple:
return static_cast<std::tuple_element_t<0u, data_type>>(
std::get<0>(_f))(std::forward<Args>(args)...);
or forward (which will have the same effect through reference collapsing):
return std::forward<std::tuple_element_t<0u, data_type>>(
std::get<0>(_f))(std::forward<Args>(args)...);

How to make constructor accepting std::function also accept method pointers

Say I have
class Foo
{
public:
Foo(std::function<void(std::string)> callback1,
std::function<void(int)> callback2) :
callback1(callback1), callback2(callback2)
{
}
private:
std::function<void(std::string)> callback1;
std::function<void(int)> callback2
}
I can easily construct it in the case I'm using plain functions
void callback1Handler(std::string)
{
// i'm a potato
}
void callback2Handler(int)
{
// i'm a teapot
}
int main()
{
Foo foo(callback1Handler, callback2Handler);
return 0;
}
But if I'm using a class, then things get complicated.
I'd like to be able to do something like the Addendum of this answer does
class Main
{
public:
Main()
{
Foo foo(&Main::callback1Handler, &Main::callback2Handler);
}
void callback1Handler(std::string)
{
// i'm a potato
}
void callback2Handler(int)
{
// i'm a teapot
}
}
But that obviously wouldn't compile. To make it work one would need to use either std::bind or lambdas, or something else.
I want to try to avoid the ugliness of std::bind(&Main::callbackNHandler, this, std::placeholders::_1, ..., std::placeholders::_N), which is mostly the ugliness of having those placeholders explicitly specified.
Using lambdas as [=](std::string str){callbackNHandler(str);} is also ugly, because you have to specify every single variable the callback accepts.
It would be great if I could just use &Main::callback1Handler, just like in the Main class example, or &Main::callback1Handler, this, which is a bit more flexible, since you can specify the instance pointer of Main.
Note that Foo constructor has to remain the same and callback1&callback2 member variables have to also remain the same. However, you may overload Foo constructor, making the overload convert method pointers (or whatever else you will make it to accept) into std::functions and store them in callback1&callback2.
template<class T, class R, class...Args>
std::function<R(Args...)> method( T* t, R(T::*m)(Args...) ){
return [=](Args&&...args)->R{
return (t->*m)(std::forward<Args>(args)...);
};
}
then method( instance, &Main::callback1Handler ) should work, up to typos.
It gets simpler in C++14.
The above does needless type erasure: a helper type instead of a lambda lets you avoid that.
template<class T, class Sig>
struct method_t;
template<class T, class R, class... Args>
struct method_t<T,R(Args...)> {
T* t;
R(T::*m)(Args...);
template<class...Ts>
R operator()(Ts&&...ts)const{
return (t->*m)(std::forward<Ts>(ts)...);
}
};
template<class T, class R, class...Args>
method_t<T, R(Args...)> method( T* t, R(T::*m)(Args...) ){
return {t, m};
}
with the same signature. It can even be stored in a std::function<R(Args...)>. The advantage of the above is that there is no needless overhead if the signature of the std::function does not exactly match, or if you don't use a std::function at all.
The downside is 3x as much code.
In C++14 we can simply do:
template<class T, class R, class...Args>
auto method( T* t, R(T::*m)(Args...) ){
return [=](auto&&...args)->R{
return (t->*m)(decltype(args)(args)...);
};
}
which is as brief as the first one, and as powerful as the second one.
Using lambdas as [=](std::string str){callbackNHandler(str);} is also ugly, because you have to specify every single variable the callback accepts.
C++14 generic lambdas solve that problem:
[this](auto... args){ callback1Handler(args...); }
For C++11 you could write a simple utility that can be used like so:
Foo foo(simple_bind(&Main::callback1Handler, this),
simple_bind(&Main::callback2Handler, this));
That would be defined as a function template like this:
template<typename T, typename F>
SimpleBinder<T, F>
simple_bind(F T::* memfn, T* that)
{ return { that, memfn }; }
Where the type SimpleBinder<T, F> is just:
template<typename T, typename F>
struct SimpleBinder
{
T* m_this;
F T::* m_memfn;
template<typename... Args>
void operator()(Args&&... args)
{ (m_this->*m_memfn)(std::forward<Args>(args)...); }
};
This isn't a fully generic utility (for example, it doesn't do anything with the return type of the member function, always returning void, but that is OK for your requirements, where both the std::function objects return void anyway), but it solves the problem of associating an arbitrary member function with a this pointer, and then calling it with some set of arguments.
Although the SimpleBind object appears to accept any arguments, in fact you'll get a nasty compiler error if you try to call it with arguments that aren't compatible with the member function it binds. Again, that's not a problem, because the std::function objects you store it in will ensure that only the right type of arguments are ever passed to it.

Checking whether a non-hardwired member function exists with SFINAE

I want to create proxies for member functions and operators. They must have the same return type and parameters, and must be good for several classes, which are given as template parameters. Even if the class does not have the particular member function or operator, I want it to compile instead of failing with an error, essentially SFINAE. If X has a method f() and Y does not have any method named f, I need Proxy<X> to have an f() as well that calls X::f(), and I need Proxy<Y> to compile and instantiate without any problems.
Extracting the return type from a known function is no longer a problem, after a previous question of mine. However it fails with an error if there is no such function.
I already know several template metaprogramming tricks to determine whether a given function exists, and enable a certain feature if they do, however, they all work only on hardwired function names instead of arbitrary ones, which severely limits their use in this case since I need the same construct for several functions.
I only need to check whether any function with the given name exists, if there are overloaded variants I do not need to check if a specific one exists, automatic template deduction solves that (or so I hope)
My current code looks like this:
template <class T>
class Proxy
{
// using my resultof solution
template <class... Args>
resultof(T::f, Args...) f (Args... x)
{
return x.f(x...);
}
// using another return type extraction solution
template <class... Args>
typeof(T::f(std::declval<Args>()...)) f (Args... x)
{
return x.f(x...);
}
T x;
};
Which should compile even if T does not have any function named f. Unfortunately both version fail with an error.
The implementation of resultof being
#define resultof(f, ...) typeof(Param<__VA_ARGS__>::Func(f))
template <class... Args>
class Param
{
public:
template <class R>
static R Func (R (*) (Args...));
template <class R, class C>
static R Func (R (C::*) (Args...));
template <class R, class C>
static R Func (R (C::*) (Args...) const);
};
I suspect that
template<typename... Args>
decltype( std::declval<T&>().f(std::declval<Args>()...) )
f(Args&&... args)
{
return x.f(std::forward<Args>(args)...);
}
should trigger SFINAE and discard any instantiation of f for which the return type is ill-formed (e.g. ambiguous or non-existant overload) instead of a hard error. I'm not quite sure though because T is a parameter of proxy, not f and I simply can't parse the relevant parts of the Standard (around 14.8.2 I believe). None of the examples provided in the non normative notes seems to apply.
Failing that, it's possible to use
template<typename U = T&, typename... Args>
decltype( std::declval<U>().f(std::declval<Args>()...) )
f(Args&&... args)
{
return x.f(std::forward<Args>(args)...);
}
for which my compiler happily accepts proxy<int> p;, unlike with the first option. p.f(); results in a 'No matching function found' error, as is usual with SFINAE.
I recommend using the freestanding form of the operators where possible:
template<typename T, typename U>
auto operator+(Proxy<T> const& lhs, Proxy<U> const& rhs)
-> decltype( std::declval<T const&>() + std::declval<U const&>() )
{
return lhs.x + rhs.x;
}
is a possibility.
At first glance, this seems trivial:
template <typename T> class Proxy : public T { };
Nothing else in C++ will give Proxy<T> all the members of T, for any T. The only bit missing is the ctors, but from your question I infer that you already know how to forward those.
Background: Practically speaking, the set of possible member names of T is infinite. Therefore, you can't find .f() by name lookup in Proxy<T>, and the only other scope in which a member name is looked up is the base class scope.
You need to isolate the checking of the existence of f in the template parameter of proxy by an extra level. The following will allow you to call proxy<X>::f() in any way that you can call X::f():
template<typename T,typename ... Args>
struct f_result
{
typedef decltype(std::declval<T&>().f(std::declval<Args&&>()...)) type;
};
template<typename T>
struct proxy
{
T val;
template<typename ... Args>
typename f_result<T,Args...>::type
f(Args&& ... args)
{
return val.f(static_cast<Args&&>(args)...);
}
};
Quick test:
#include <iostream>
struct X
{
void f()
{
std::cout<<"X::f()"<<std::endl;
}
int f(int i)
{
std::cout<<"X::f("<<i<<")"<<std::endl;
return i;
}
};
struct Y
{};
struct Z
{
int f()
{
std::cout<<"Z::f()"<<std::endl;
return 42;
}
};
int main(int, char**)
{
proxy<X> px;
px.f();
int i=px.f(3);
std::cout<<"i="<<i<<std::endl;
proxy<Y> py;
proxy<Z> pz;
int j=pz.f();
std::cout<<"j="<<j<<std::endl;
}
This works OK with g++ 4.5 and g++ 4.6 in -std=c++0x mode.