I need to do something like this:
template<class A=B, class B>
A fn(B x) { return A(x); };
int main()
{
int i = fn(5); // Error, no matching overload found
double d = fn<double>(5);
};
Hence, a function template which deduces the types automatically from the function arguments, but the caller can change the first one if needed. Any way to do this?
You can simply use constexpr if in such cases like:
struct NO_TYPE;
template<class RET_TYPE = NO_TYPE, class IN_TYPE>
auto fn(IN_TYPE x)
{
if constexpr ( std::is_same_v< RET_TYPE, NO_TYPE> )
{
std::cout << "1" << std::endl;
return IN_TYPE(x);
}
else
{
std::cout << "2" << std::endl;
return RET_TYPE(x);
}
}
int main()
{
int i = fn(5); // Error, no matching overload found
double d = fn<double>(5);
};
Related
I would like to improve the code so that it is convenient to interact with it.
struct prototype {
template <class... T1>
prototype(T1&&... args) {
auto p = std::tie(args...);
std::cout << std::get<0>(p) << std::endl;
if constexpr(std::tuple_size_v<decltype(p)> >= 3) {
std::cout << std::get<2>(p) << std::endl;
}
}
};
int option_1 = 10;
std::string option_2 = "test2";
auto option_3 = 0.41;
std::vector<int> option_4(10);
int main() {
prototype p1(option_1, option_2, option_3, option_4);
prototype p2(option_1, option_2, option_3);
prototype p3(option_1, option_2);
prototype p4(option_1);
}
i would like to do so
std::cout << option_1 << std::endl;
if constexpr (std::tuple_size_v<decltype(p)> >= 3) {
std::cout << option_2 << std::endl;
}
I don't like this option std::get<0>(p)
Any ideas how to replace the call to tuple?
You can also see the option on https://godbolt.org/z/bT4Wzjco8
You can create a variable template out of a lambda. At the end of the day all you want is a compile time constant to pass to std::get:
template <std::size_t N>
constexpr auto option = [] (auto p) -> auto&& { return std::get<N-1>(p); };
This can be used as option<1>(p)
Demo
The familiar template syntax for lambdas may seem as another alternative:
constexpr auto option = []<std::size_t N>(auto p) { return std::get<N-1>(p); };
Here the argument to std::get is passed as a non type template parameter. As #Davis Herring mentions, this unfortunately does not mean the lambda is then to be used as option<1>(p). The reason being that the lambda is not itself a template, its function call operator is. The proposal changes nothing on the templateness of the lambda itself. As a result the lambda above is invocable as
option.operator()<1>(p)
Demo
I am creating a class that allows me to store lambdas that need to be executed (in order) at a point in the future.
class Promise{
private:
//snip//
std::vector<std::function<void()>> lchain;
public:
//snip//
void then(const std::function<void()> &f){
if (this->resolved) {//If the promise is resolved we just call the newly added function, else we add it to the lchain queue that will be processed later
f();
return;
}
lchain.push_back(f);
}
void launch(){
this->resolved = true;
for (auto &fun: this->lchain)
fun();
}
}
It is obvious that it will only work with lambdas with a signature like [&](){} but some of the tasks need to work with an arbitrary number of parameters of arbitrary types (both, parameters and types are known in advance, when the function is added to the queue).
An example driver program that currently works is
int main(){
Promise* p = new Promise([](){
std::cout << "first" << std::endl;
})->then([](){
std::cout << "second" << std::endl;
});
Promise->launch(); //In my code promise chains are picked up by worker threads that will launch them.
}
An example program I would like to execute:
int main(){
Promise* p = new Promise([](){
return 5;
})->then([](int n){
return n*n;
})->then([](int n){
std::cout << n << std::endl; //Expected output: 25
});
Promise->launch();
}
Things that I am struggling to do:
Storing lambdas of mixed signatures in a std::vector
Making the then() method call f with the arguments associated with f
Making the then() function return the result of f so it can be fed to the next lambda in the chain (preferably binding it before storing the lambda in the vector)
I have been searching in stackoverflow the whole day but the closest I got was this but I would like something that can be done in the then() method to simplify the program code as it would be a pain to bind every single lambda before calling the then() method.
I have something that I think does what you want. I'll start with an example and then introduce the implementation.
int main(){
Promise p([] {
return 5;
});
p.then([](int n) {
return n*n;
}).then([](int n) {
std::cout << n << '\n';
});
p.launch();
struct A { int n; };
struct B { int n; };
struct C { int n; };
Promise q([](A a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{2};
});
q.then([](B b) {
std::cout << "B " << b.n << '\n';
return C{3};
}).then([](C c) {
std::cout << "C " << c.n << '\n';
});
q.launch(A{1}, 111);
Promise<B(A, int)> r([](auto a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{5};
});
r.then([](auto b) {
std::cout << "B " << b.n << '\n';
return C{6};
}).then([](auto c) {
std::cout << "C " << c.n << '\n';
});
r.launch(A{4}, 222);
}
This outputs:
25
A 1 111
B 2
C 3
A 4 222
B 5
C 6
Some drawbacks:
Calling then after the promise has been resolved doesn't automatically call the function. Things get confusing in that situation and I'm not even sure if it's possible.
You can't call then multiple times on the same promise. You have to build a chain and call then on the result of the previous then.
If any of those drawbacks make this unusable, then you can stop reading this humongous answer.
The first thing we need is a way of getting the signature of a lambda. This is only used for the deduction guide so it isn't strictly necessary for the core concept to work.
template <typename Func>
struct signature : signature<decltype(&Func::operator())> {};
template <typename Func>
struct signature<Func *> : signature<Func> {};
template <typename Func>
struct signature<const Func> : signature<Func> {};
template <typename Ret, typename... Args>
struct signature<Ret(Args...)> {
using type = Ret(Args...);
};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...)> : signature<Ret(Args...)> {};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...) const> : signature<Ret(Args...)> {};
template <typename Func>
using signature_t = typename signature<Func>::type;
The next thing we need is a base class. We know the next promise must accept the return type of the current promise as an argument. So we know the argument type of the next promise. However, we don't know what the next promise will return until then is called so we need a polymorphic base to refer to the next promise.
template <typename... Args>
class PromiseBase {
public:
virtual ~PromiseBase() = default;
virtual void launch(Args...) = 0;
};
Now we have the Promise class itself. You can construct a promise with a function. As I alluded to above, a promise stores a pointer to the next promise in the chain. then constructs a promise from the given function and stores a pointer to it. There is only one next pointer so you can only call then once. There's an assertion to make sure this doesn't happen. launch calls the stored function and passes the result to the next promise in the chain (if there is one).
template <typename Func>
class Promise;
template <typename Ret, typename... Args>
class Promise<Ret(Args...)> : public PromiseBase<Args...> {
public:
template <typename Func>
explicit Promise(Func func)
: handler{func} {}
template <typename Func>
auto &then(Func func) {
assert(!next);
if constexpr (std::is_void_v<Ret>) {
using NextSig = std::invoke_result_t<Func>();
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
} else {
using NextSig = std::invoke_result_t<Func, Ret>(Ret);
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
}
}
void launch(Args... args) override {
if (next) {
if constexpr (std::is_void_v<Ret>) {
handler(args...);
next->launch();
} else {
next->launch(handler(args...));
}
} else {
handler(args...);
}
}
private:
using NextPromise = std::conditional_t<
std::is_void_v<Ret>,
PromiseBase<>,
PromiseBase<Ret>
>;
std::unique_ptr<NextPromise> next;
std::function<Ret(Args...)> handler;
};
Finally, we have a deduction guide.
template <typename Func>
Promise(Func) -> Promise<signature_t<Func>>;
Here's an online demo.
I ran into this problem earlier today. In the following code:
template <int> struct Holder {};
template <typename> struct Helper { using T = Holder<__COUNTER__>; }; // ???
int main() {
auto a = typename Helper<bool>::T();
auto b = typename Helper<int>::T();
std::cout << (typeid(a) == typeid(b)) << std::endl;
return 0;
}
When compiled and executed with:
g++ test.cpp -std=c++11 -o test
./test
It prints out 1 instead of 0, meaning that the 2 Ts in Helper<int> and Helper<bool> are the same type, which makes me wonder:
Why the line marked with // ??? is executed only once instead of once for each of the type?
Is there a way to force the line to be executed once for each of the type and preferably without modifying the definition of Holder?
====================================================
Clarifications:
The (closer to) real scenario is:
The struct Holder is defined in a header from a third-party library. The type for the struct is actually very complicated and the library writer provides users with another macro:
template <bool, int> struct Holder {};
#define DEF_HOLDER(b) Holder<b, __COUNTER__>()
At some point of the program, I want to take a "snapshot" of the type with current counter by aliasing the type so that it could be used in a function:
template <bool b>
struct Helper { using T = decltype(DEF_HOLDER(b)); };
template <bool b, typename R = typename Helper<b>::T>
R Func() {
return R();
}
// Note that the following does not work:
// Since the 2 types generated by DEF_HOLDER do not match.
template <bool b>
auto Func() -> decltype(DEF_HOLDER(b)) {
return DEF_HOLDER(b);
}
The problem here is that the following 2 usage has inconsistent semantics as illustrated:
int main() {
auto a = DEF_HOLDER(true);
auto b = DEF_HOLDER(true);
auto c = Func<true>();
auto d = Func<true>();
std::cout << (typeid(a) == typeid(b)) << std::endl; // prints 0
std::cout << (typeid(c) == typeid(d)) << std::endl; // prints 1
return 0;
}
In my use case, it is important for multiple invocation of Func to return different types as it does with invoking DEF_HOLDER directly.
The symbol __COUNTER__ is a preprocessor macro, it's expanded once only.
That means T will always be Holder<0> (since __COUNTER__ starts at zero), no matter the type used for the template Helper.
See e.g. this GCC predefined macro reference for more information about __COUNTER__.
I am not sure whether I completely understand the problem, but since C++14 there is no need to use DEF_HOLDER two times. The following code also works:
template <bool b>
auto Func() {
return DEF_HOLDER(b);
}
If you want a different type for every function call, you can add the int parameter:
template <bool b, int i>
auto Func()
{
return Holder<b, i>();
}
You could hide this int in a macro:
#define FUNC(b) Func<b,__COUNTER__>();
Then a,b and c,d have the same semantics:
int main() {
auto a = DEF_HOLDER(true);
auto b = DEF_HOLDER(true);
auto c = FUNC(true);
auto d = FUNC(true);
std::cout << (typeid(a) == typeid(b)) << std::endl; // prints 0
std::cout << (typeid(c) == typeid(d)) << std::endl; // prints 0
return 0;
}
I have the following code:
#include <functional>
//...
typedef int (*Myfun)(int);
std::function<int (int)> fn0([](int a)->int {
return -a;
});
std::cout << "val == " << fn0(3) << std::endl; //"val == -3"
Myfun *fptr = fn0.target<Myfun>(); //fptr is NULL!!
std::cout << "val == " << (*fptr)(3) << std::endl; //Access violation error
Actually, this code is a code from MSDN with a slight change: using lambda instead of a plain function.
Why does the call fn0.target<Myfun>() returns NULL?
When I declare a regular function
int neg(int val) {
return (-val);
}
and write std::function<int (int)> fn0(neg);, everything seems to work, but lambda is not been handled correctly.
The type Myfun from typedef int (*Myfun)(int); is not related to the type of the function's target, which is the unique, unnamed type of the closure object produced by executing the expression [](int a)->int { return -a; }
Try executing std::cout << fn0.target_type().name() << '\n'; to see for yourself.
When you declare a function with int neg(int val) { return (-val); }, the type of neg is exactly Myfun (after function-to-pointer conversion, which happens in std::function<int(int)> fn0(neg)), which is why std::function::target() is able to return a pointer to it.
Cubbi explained why your code doesn't work -- a lambda is not a function pointer.
Now, trivial lambdas can be converted to function pointers. So supposed you really want to force that conversion?
template<typename F>
struct as_pointer_t {
F f;
template<typename R, typename... Args>
operator type<R(*)(Args...)>() const { return {f}; }
template<typename R, typename... Args>
operator std::function<R(Args...)>() const { return (R(*)(Args...))f; }
};
template<typename F>
as_pointer_t<F> as_pointer( F&& f ) { return {std::forward<F>(f)}; }
now we can do this:
int main() {
typedef int (*Myfun)(int);
std::function<int (int)> fn0(as_pointer([](int a)->int {
return -a;
}));
std::cout << "val == " << fn0(3) << std::endl; //"val == -3"
Myfun *fptr = fn0.target<Myfun>(); //fptr is no longer NULL!!
std::cout << "val == " << (*fptr)(3) << std::endl;
}
and your code works as expected. However, the above only compiles if your lambda captures nothing.
If your goal is to convert a capturing lambda to a function pointer, you cannot. You can store the state in a global variable, and use it in a non-capturing lambda. You can also convert a capturing lambda into a function-pointer and void* pair.
I have written code that takes a compile-time index to inject the void* into the list (and an optional type to use instead of void*), and produces said pair of void* and function pointer. The general case is tricky -- the specific case (say, the first argument) is far easier.
template<typename T> using type=T;
template<typename F, typename X=void*>
struct callback_t {
F f;
operator X() { return X(&f); }
template<typename R, typename...Args>
operator type<R(*)(X, Args...)>() const {
return []( X x, Args... args )->R {
F* f = (F*)(x);
return (*f)(std::forward<Args>(args)...);
};
}
};
template<typename X=void*, typename F>
callback_t<F,X> make_callback( F f ) {
return {std::forward<F>(f)};
}
use:
typedef void(*pfun)(void*, int);
void call_pfun( pfun f, void* p) {
for (int i = 0; i < 3; ++i)
f( p, i );
}
int main()
{
int y = 7;
auto callback = make_callback([y]( int x ) { std::cout << x+y << "\n"; });
call_pfun( callback, callback );
}
live example.
Is it possible to declare a function bar to have the same signature as function foo?
int foo(int a)
{
return 0;
}
decltype(foo) bar
{
return 1;
} //imaginary syntax
I think the same applies as for typedefs and aliases: You may use decltype to declare a function, but not to define it:
int foo();
decltype(foo) bar;
int foo()
{
return bar();
}
int bar() { return 0; }
is accepted by clang++3.5 and g++4.8.1
[dcl.fct.def.general]/2 forbids (grammatically) the definition of a function w/o parentheses:
The declarator in a function-definition shall have the form
D1 ( parameter-declaration-clause ) cv-qualifier-seqopt
ref-qualifieropt exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt
as described in 8.3.5.
You can use variadic templates to define a function which has the same signature as any function:
#include <iostream>
int foo(char const *blah) { return 0; }
template<typename... Args>
auto bar(Args ... args) -> decltype(foo(args...))
{
return 1;
}
int main() {
std::cout << foo("test") << std::endl;
std::cout << bar("test") << std::endl;
return 0;
}
This could also be modified slightly to pass "foo" as the first template argument, so that you could use the same "bar" with many different "foo"s:
template<typename Func, typename... Args>
auto bar(Func f, Args ... args) -> decltype(f(args...))
{
return 1;
}
int baz(double d) { return 3; }
int main() {
std::cout << bar(&foo, "test") << std::endl;
std::cout << bar(&baz, 1.2) << std::endl;
return 0;
}
The first thing that comes into mind is that you need to name the parameters so no, you can't.
The type of foo is:
int(int)
so any imaginary declaration syntax like:
decltype(foo) bar { //imaginary syntax
// can't access parameter
return 1;
}
will have the problem that bar can't access parameters.
So the best you can do is what #dyp suggests.
One other thing you could do is to check if two functions have the same signature:
static_assert(std::is_same<decltype(foo), decltype(bar)>::value, "Invalid bar signature");
Not trivially as you're posing, since you cannot set the arguments directly. decltype(foo) does return the actual type of foo, so you can use that to instantiate a template traits class that then exposes the return type and arguments type (somehow), and then use that to define your function.
#include <stdio.h>
int sf(int, float, double, bool) {}
template <typename RV, typename... args>
RV func(args... as) {
printf("%d %f %f %d\n", as...);
return sf(as...);
}
template <typename RV, typename... args>
RV(*generateFunc(RV(*)(args...)))(args...) {
return &func<RV, args...>;
}
int main() {
decltype(sf) *f = generateFunc(sf);
f(42, 1.0f, 12.0, true);
}
This generates a function to match sf's signature and then forwards the call to it.