0

I got a problem on where I have something like this:

#define A_BODY printf("b is %s and c is %d, typeless! :3\n", b, c);
#define B_BODY return "test";
#define C_BODY return 42;

I need to make a code that would, for example, call a(b(), c()), with their respective types.

On C++14 I can easely do this:

template<typename B, typename C> auto a(B &&b, C &&c) {
  A_BODY
};
auto b() {
  B_BODY
};
auto c() {
  C_BODY
};

int main() {
  auto _b = b();
  auto _c = c();
  auto _a = a(_b, _c);

  return 0;
};

Achieving the desired result... is there any way to get the same result on C++11? :'(

Also, they can call each other recursively, so a simple ordering here wouldn't help either.

Edit

I will try to explain better my situation.

I got an input file like this, for example:

a is b c {
  printf("b is %s and c is %d\n", b, c);
  if(c > 42)
    printf("c is bigger than the truth!\n");
  return strlen(b) + c;
};
b is {
  return "test";
};
c is {
  return 42;
};

And I need to generate a C++ code that can properly call them. I'm trying to infer the return types without needing to define them on the input file.

From that, I can get the *_BODY specifications, the number of parameters, and the order of calls, but I don't know which type the parameters will be. So I'd need an templated lambda, for example, to do lazy evaluation of the function body.

I can do this with C++14 on GCC and CLang, but this is a commercial project and I need to support Visual Studio 2012 as well. I'm trying to find a workaround, if there is any. :(

paulotorrens
  • 2,286
  • 20
  • 30
  • 3
    Since `b` must be `char const *` and c` must be `int`, maybe this example isn't the most representative of your problem? – Kerrek SB Sep 11 '13 at 20:51
  • The thing is that `b` could be something different from `const char *`. This code should run on a **generated file**, thus `A_BODY`, `B_BODY`, `C_BODY`, and etc, could have any return types. The only thing is that some are parameters to others. Just consider that it should work with any return types on the `*_BODY`. – paulotorrens Sep 11 '13 at 20:56
  • Hm, but if `b` is anything different, then your `A_BODY` is UB :-S – Kerrek SB Sep 11 '13 at 21:01
  • 1
    Can't whoever generates `A_BODY`, `B_BODY` and `C_BODY` also generate `A_RETURN_TYPE`, `B_RETURN_TYPE`, and `C_RETURN_TYPE` appropriately? They must know, or they wouldn't be able to synthesize `%s` and `%d`. – Igor Tandetnik Sep 11 '13 at 21:17
  • Perhaps relevant: http://stackoverflow.com/a/18432618/85371 (not so sure what you mean due the samples chosen) – sehe Sep 11 '13 at 22:20
  • It will generate for a file containing the bodies: the user will expect B and C to return those values, that's why A would be that code. Of course if you change the return type of B your A body would have to change, as well. This looks like the input from whence I will get the `*_BODY`: http://pastebin.com/1r1UmsPa. See? The user will right the functions properly (otherwise the generated code won't compile). Think of that as a Yacc/Bison/Peg-like tool. – paulotorrens Sep 11 '13 at 23:47
  • The polymorphic lambda @sehe posted won't help because I don't know the return types of `b` and `c`, thus `a` must be a template in order to lazy-evaluate the body of the function. :( – paulotorrens Sep 11 '13 at 23:50

1 Answers1

1

Could do it like this:

#define A_EXPR printf("b is %s and c is %d, typeless! :3\n", b, c)
#define B_EXPR "test"
#define C_EXPR 42

template<typename B, typename C> auto a(B &&b, C &&c)
    -> decltype(A_EXPR) { return A_EXPR; }
auto b() -> decltype(B_EXPR) { return B_EXPR; }
auto c() -> decltype(C_EXPR) { return C_EXPR; }

int main() {
  auto _b = b();
  auto _c = c();
  auto _a = a(_b, _c);
  return 0;
};

Works fine in clang. On the other hand, gcc (4.8.1) complains that

sorry, unimplemented: string literal in function template signature

for function a, but you don't really need a result for that; it could be just void.

iavr
  • 7,547
  • 1
  • 18
  • 53
  • The problem is that, by design, I need a `return` statement on the `*_BODY`'s. I wish I could do something like `decltype(return 42;)`, `decltype([]{ return 42; })` or `decltype( ({ return 42; }) )`. Tested on GCC and CLang, neither accepts it. I'm trying to find a workaround in order to keep using the `return` statements (I need it portable, and Visual C doesn't accept C++1y). :( – paulotorrens Sep 11 '13 at 23:16
  • Actually, CLang accepted `decltype( ({ return 42; }) )`. GCC did not. I'll check with Visual Studio later; if it works, maybe could be an option. – paulotorrens Sep 11 '13 at 23:51
  • Both GCC and CLang accepted `typeof( ({ 42; }) )`, but Visual Studio did not. Sadly I need to support Visual Studio. :'( – paulotorrens Sep 12 '13 at 00:18
  • 2
    @PauloTorrens: The name is "Clang" (lowercase 'L'), and it's *not* pronounced "C-Lang (See-Lang)". It's pronounced "Klang". Sorry, pet-peave. :) – Xeo Sep 12 '13 at 17:41
  • @Xeo: Deep within my heart it will always be see-lang. ;) – paulotorrens Sep 12 '13 at 19:13