Home > Mobile >  Exclude Macro, What can I use like inline function in C
Exclude Macro, What can I use like inline function in C

Time:09-15

I don't want to edit the common part of the source code repeatedly.

So I separate the other parts with different functions as below.

/* Origin */
void MyClass::threadFunc_A()
{
    // many variables in this function
    ...

    // do something A
    ...
}

void MyClass::threadFunc_B()
{
    // many variables in this function
    ...

    // do something B
    ...
}

/* I wish */
void MyClass::threadFunc(type)
{
    // many variables
    int a, b;
    char c, d, e;
    ...
    string x, y, z;
    ...

    // case
    if (type == A) do_something_A();
    if (type == B) do_something_B();
    ...
    if (type == Z) do_something_Z();
}

void do_something_A()
{
   // using "many variables (a ~ z)" here
   a = 10;
   b = 20;
   ...
}

In the case of macro functions, I know that the code is built in when compiling, so that variables within the same range can be used.

However, if the do_something() function is lengthened, there is a limit to writing using the macro function.

Is there a way to write an inline function like 'I wish' in C 17 or higher? (Except for putting A as a member variable of the class or making it a structure and passing it)

CodePudding user response:

No there is no way to do that. C has lexical scoping. What you want would be (at least partially) more like dynamic scoping.

The point of a function is that it separates some part of the logic into a self-contained block of code that can be reused. If you make the name resolution in the function dependent on the declarations at the call site, it becomes impossible to reason about the behavior of the function without also specifying the call site.

Macros effectively do behave that way, but that is not a good thing. It is one of the reasons to avoid them.

C does have templates, which allows making similar logic independent of concrete types in a function, but that still doesn't allow making name resolution dependent on the call site.

Write your functions so that they represent a part of the program logic that makes sense in itself. The function should take all variables to which it needs access as arguments, possibly with templated types, and if it needs to work on an unspecified number of arguments, possibly of different types, it can be a variadic function template. If there are many variables with similar meaning, consider putting them in an array or container or class combining them into one unit that makes sense in the program logic.

CodePudding user response:

I am not aware of a way to literally use a typename as a function parameter; except for specialized functions such as sizeof().

Some more normative ways to approach it would be:

  • Use an enum representing types, to pass to threadFunc().
  • Make a function in your class for each types, as overrides; and pass it a value of the type in question.
  • Make a function parameter std::variant, and pass it a value of the type in question. That way, you can inspect it to see which of the types it supports it is, using the ::index() property; or if you're using the Qt framework, QVariant() can get a dummy QVariant of the type with QVariant::type() that you can compare to, or a string as the typename, with QVariant::typename().
  • This SO ? purports to shows how to use a template to allow a typename as a function parameter: "https://stackoverflow.com/questions/937268/how-to-take-a-typename-as-a-parameter-in-a-function-c"; although the answers only have it to work for multiple return types.

One downside of putting large blocks of code in C macros, is they can be hard to debug; as they probably won't have syntax highlighting or in-editor syntax checking. Also, the debugger may treat the whole block as a single line.

  • Related