-2

For my program (C++), I need to read one of the function parameter as it is given while calling the function, for example:

void foo(int arg)
{
// I need to read the "arg" parameter here, not its value but the exact thing passed while calling the "foo" function
}

for example:
int bar = 10;
foo(bar); // I want to read "bar" string

Is there a way to do that?

One of the alternate option I can see is make two parameters and call the function like:

foo(bar, "bar");

I'm a beginner in c++, so it may be a silly question...

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
DonBaka
  • 325
  • 2
  • 14
  • 4
    Why do you need it? – n. m. could be an AI Oct 07 '21 at 08:29
  • 3
    C++ is a compiled language without built-in reflection. -> Identifiers (type names, variable names, function names, etc.) are beyond of scope in the executable. Your 2nd option is in fact the only one - adding some kind of reflection by your own code. Btw. while macros are considered as bad in C++, they can be useful for cases like your. There is a ["stringize" macro command](https://en.cppreference.com/w/cpp/preprocessor/replace#.23_and_.23.23_operators): `#arg` results in `"arg"`. – Scheff's Cat Oct 07 '21 at 08:30
  • 4
    It sounds like an [XY problem](https://meta.stackexchange.com/q/66377/455871). – Daniel Langr Oct 07 '21 at 08:31
  • @n.1.8e9-where's-my-sharem. I'm writing a wrapper for `boost` `numeric_cast` and I want to throw the exception something like `numeric_cast failed for field: var-name, fromType: int, fromValue: 32768, toType: short`, that is including the variable name on which the numeric_cast is called to use it for debugging easily – DonBaka Oct 07 '21 at 08:34
  • 1
    For such case, usually another trick is used (e.g. in [assert()](https://en.cppreference.com/w/cpp/error/assert)): [SO: \_\_FILE\_\_, \_\_LINE\_\_, and \_\_FUNCTION\_\_ usage in C++](https://stackoverflow.com/a/597081/7478597). This gives you exact coordinates for where to look into the source code. (Of course, this is not useful for complaints to end users, just for those who are expected to have access to the source code.) – Scheff's Cat Oct 07 '21 at 08:36
  • 3
    You can't. It might not *be* a named variable. It might be a numeric literal, or an expression, or the result of a cast, or ... – user207421 Oct 07 '21 at 08:40

1 Answers1

4

AS there is no build-in reflection in C++, in resulting code all ids will be gone. But you can emulate it by using stringize operator #, if you don't mind to use some wrappers. assert() macro in some implementations makes use of it.

#include <iostream>

void order(int arg1, int arg2, const char* str)
{
    std::cout << str << arg1*arg2 << std::endl;
}

#define REFLECT_INVOKE(func, ...) (func)(__VA_ARGS__, #func "("  #__VA_ARGS__ ") = ")

int main()
{
    int x = 6;
    int y = 11;
    REFLECT_INVOKE(order,x,y);
}

Output:

order(x,y) = 66

Operator # literally wraps following token in quotes before placing result into processed source before compilation, so statement REFLECT_INVOKE(order,x,y); is processed into (order)(x,y,"order" "(" "x,y" ") = ");

We can make it a bit more universal, using new features (there is probably simple and obvious way to do this):

int order(int arg1, int arg2)
{
    return arg1*arg2;
}

template<class F, class ...Args> 
auto debug_call( F func, const char* str, Args... args) -> 
     decltype(std::forward<F>(func)(std::forward<Args>(args)...))
{
    if constexpr ( std::is_same<decltype(std::forward<F>(func)(std::forward<Args>(args)...)),void>::value) {
        std::cout << str;
        func(args...);
    } else {
        auto res = func(args...);
        std::cout << str << "= " << res;
        return  res;
    }
}

#define REFLECT_INVOKE(func, ...) (debug_call)(func, #func "(" #__VA_ARGS__ ") ", __VA_ARGS__)

int main()
{
    int x = 6;
    int y = 11;
    REFLECT_INVOKE(order,x,y);
}

This is barely usable outside of debugging purposes.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42