1

I have a c++ library which has an function called ExampleFunction(). This function is documented and is already in use. Unfortunately, the style of the library requires this function to be called exampleFunction() {initial letter is lowercase}.

I need to keep the old name for backwards compatibility but add the new name as a public function. What is the most efficient way to do this?

I am assuming that adding a definition of:

void exampleFunction() {ExampleFunction();}

is not the best way of solving this and am looking for options.

Marek R
  • 32,568
  • 6
  • 55
  • 140
SV-Zanshin
  • 13
  • 2
  • `I am assuming that adding a definition of "void exampleFunction() {ExampleFunction(); return;}" is not the best way` read about "As if" rule and reconsider your statement. – Marek R Jun 29 '20 at 14:19
  • 1
    At the source level that's probably the best you can do. If you're lucky the compiler's optimizer might do tail-call elimination and do a jump from `exampleFunction` to `ExampleFunction`. – 500 - Internal Server Error Jun 29 '20 at 14:19

3 Answers3

3

I am assuming that adding a definition of "void exampleFunction() {ExampleFunction(); return;}" is not the best way of solving this

I recommend to not assume such thing. That is a fine way to solve this.

am looking for options.

Another option is to use a function reference (or alternatively a function pointer):

auto& exampleFunction = ExampleFunction;
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Don't we need any parenthesis in case we define a function reference (and not a variable)? – Rohan Bari Jun 29 '20 at 14:24
  • I think their comment was just a turn of phrase. They've basically asked "Is there a better way to do this?" and you've replied "What makes you think that there is? By the way, here's one." – Arthur Tacca Jun 29 '20 at 14:26
  • @ArthurTacca I didn't say that the alternative is better. – eerorika Jun 29 '20 at 14:27
  • 1
    @RohanBari A function reference **is** a variable. No parenthesis are needed. – eerorika Jun 29 '20 at 14:28
  • Indeed it's debatable. I think the function reference is cleaner, you don't need to update it if parameter list or return type changes. But it won't reflect default arguments and will not work if there are multiple overloads. – Arthur Tacca Jun 29 '20 at 14:29
  • Unfortunately that solution does not compile, it returns an error "error: invalid use of non-static member function...". – SV-Zanshin Jun 29 '20 at 14:30
  • This is microoptimalization I would bother to investigate it. I wouldn't be surprised if for compiler both versions are 100% equivalent. – Marek R Jun 29 '20 at 14:31
  • I should add that I need to do this for several functions, none of which are overloaded but all of which have one or more parameters. For example, one of the functions is declared as "bool AlertOnBusOverVoltage (const bool alertState, const int32_t milliVolts, const uint8_t deviceNumber = UINT8_MAX);" in the header file – SV-Zanshin Jun 29 '20 at 14:36
  • @SV-Zanshin please include necessary information in the quesiton. Eg there is no member function in your question – 463035818_is_not_an_ai Jun 29 '20 at 14:36
2

You could rename the existing function that actually has the implementation to exampleFunction(), since that's what it should be. Then, so users of the old name 1) still have working code, and 2) are told that there's a newer function name to use, you can do this:

[[deprecated("Use exampleFunction() instead")]]
inline void ExampleFunction() { exampleFunction(); }

This uses the deprecated attribute from C++14 and later. The performance hit for the wrapper function is either non-existent (if really inlined by the compiler) or negligible.

Jordan
  • 1,375
  • 14
  • 17
Kevin
  • 6,993
  • 1
  • 15
  • 24
  • This is for a library on an Arduino (Atmel 8-bit processor) with little memory. Unfortunately the compiler in use is 7.3.0 so the deprecated attribute doesn't work (but at least it doesn't cause a compilation error), and the loader doesn't like it when I specify inline, but this solution is the one I'm going to use - it works and also satisfies Occam's Razor. – SV-Zanshin Jun 29 '20 at 15:06
1

As an alternative to other answers, you can use variadic templates, perfect forwarding and decltype(auto).

template<typename ...Args>
[[deprecated("use exampleFunction")]] decltype(auto) ExampleFunction(Args &&...args)
{
    return exampleFunction(std::forward<Args>(args)...);
}

You could define a macro for declaring these functions:

#define def_deprecated_func(old_name, new_name)                          \
template<typename ...Args>                                               \
[[deprecated("use " #new_name)]] decltype(auto) old_name(Args &&...args) \
{                                                                        \
    return new_name(std::forward<Args>(args)...);                        \
}

// ...

def_deprecated_func(ExampleFunction, exampleFunction)

Compile errors won't be great for the deprecated functions, but seeing as you shouldn't use them in the first place, that's not really a compromise.

Note, that this requires you to rename the original function from ExampleFunction to exampleFunction.

IlCapitano
  • 1,994
  • 1
  • 7
  • 15