VoidParam Puzzle -- Alex Marmer

Alex Marmer has openend a puzzle.

VoidParam Puzzle 

From the article:

How to handle 'void' parameter passed in a macro. He provides a solution as well.

In case that you have other or better solutions, don't hesitate to use the comment option on this site.

Add a Comment

Comments are closed.

Comments (4)

0 0

Philipp Lenk said on Jun 3, 2016 07:20 AM:

Interesting problem. Here is an alternative to the solution provided(which works with a few simple examples. I have not extensively tested it and dont really think it is very good, but maybe it amuses someone wink):


#include <stdexcept>
#include <type_traits>

template <typename T>
T Process(const T& t) { return t; }

inline void Process()
{
throw std::runtime_error("'void' parameter is not allowed");
}

template <typename T> void call_proxy(T fun, std::false_type) { Process(fun()); }

//template <typename T> void call_proxy(T fun, std::true_type)=delete;
template <typename T> void call_proxy(T fun, std::true_type) { fun(); Process(); }

template <typename T> void call_proxy(T fun) { call_proxy(fun, std::is_same<std::result_of_t<T()>,void>{}); }

#define PROCESS(x) call_proxy([&](){ return x; })

void GetVoid() {}

int main()
{
PROCESS(1);

float f=6.28;
PROCESS(f);

PROCESS(GetVoid());

PROCESS(void());

}



It is based on the fact that whilst passing void might not be possible, it is in fact perfectly legal to return it(http://stackoverflow.com/questions/3383090/is-returning-void-valid-code).
A simple template and lambda expression construct and pass a callable returning void or the desired argument, allowing us to select the called function based on the type of this expression.

Furthermore, since types are known before runtime, the error can be "lifted" to compiletime, for instance by explicitly deleting the disallowed version(the commented line above).

As mentioned, this is most likely a rather suboptimal way to do this and i wouldnt be surprised if it contains numerous problems i failed to mention.
1 0

Alex Marmer said on Jun 3, 2016 04:10 PM:

Philipp,

The problem using a lambda function in a macro - temporary variable passed as a parameter will be destructed before Process is called. For instance PROCESS(X(Y())), ~Y will be called before Process is called, which is not expected.
1 0

Alex Marmer said on Jun 4, 2016 02:10 AM:

Philipp,

In code bellow, in Process, t.n_ will have invalid stack value since ~B will be called in lambda function before Process is called.


struct B
{
int n_;

B(int n) : n_(n) {}
};

struct A
{
const int& n_;

A(const B& b) : n_(b.n_) {}
};

void main()
{
PROCESS(A(B(1)));
}
0 0

Philipp Lenk said on Jun 4, 2016 01:17 PM:

Thanks for the explanation, I did not consider this wink