1

Let's say I have a function called get_color:

std::string get_color()
{
    return "green";
}

I also want to have the same function but with the en-gb spelling, which is get_colour. I could just make an identical function and call the get_color function like this:

std::string get_colour()
{
    return get_color()
}

but this can get very tricky to maintain. Is there any other way to give a second name to a function?

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Do any of these ideas work for you? https://stackoverflow.com/questions/22582666/providing-a-function-alias-in-gcc – John Zwinck Sep 04 '20 at 12:31
  • @JohnZwinck those seem to be MSVC-specific and more about mangling than aliases. – Aaron D. Marasco Sep 04 '20 at 12:33
  • See here. That should works for you: https://stackoverflow.com/questions/4178028/giving-a-function-implementation-more-than-one-name-in-c – D. Caruso Sep 04 '20 at 12:33
  • @t.niese nice find; voting to close as dupe – Aaron D. Marasco Sep 04 '20 at 12:33
  • 3
    So you would use either use perfect forwarding or you could use `constexpr auto get_colour = get_color;` – t.niese Sep 04 '20 at 12:34
  • why is it tricky to maintain? – 463035818_is_not_an_ai Sep 04 '20 at 12:35
  • @idclev463035818 whenever you want to change the function parameters, you will have to change the first function and the second –  Sep 04 '20 at 12:37
  • @Bathsheba why overthinking. `constexpr auto alternative = alternitive;` or `constexpr auto alternative(alternitive);` and your `auto alternative(alternitive);` are not that far off, except that the for `constexpr` version tje compiler will directly call `alternitive`, because `alternative` can't change. Not sure why you removed the duplicate? – t.niese Sep 04 '20 at 13:15
  • @t.niese. Never mind about the duplicate find, what's done is done. However, you ought to put your answer-disguised-as-a-comment as an answer, as it's better than mine. – Bathsheba Sep 04 '20 at 13:19
  • @Bathsheba I wrote it only as an additional comment just to hint to the correct answer, because I already linked to the duplicate that shows `constexpr auto get_colour = get_color;` as solution. – t.niese Sep 04 '20 at 13:21
  • This is a bad idea. It makes code much harder to read, since two apparently different things are actually the same thing. – Pete Becker Sep 04 '20 at 14:01

6 Answers6

3

A C-style macro would work, but I'm not a fan of macros.

#define get_colour(x) get_color(x)

Aaron D. Marasco
  • 6,506
  • 3
  • 26
  • 39
3
auto get_colour(get_color);

is one way. Needs a little more thought if you want to support overloaded functions.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
2

I only write it here as an answer because I can't mark it as a duplicate to C++11: How to alias a function? or How do I assign an alias to a function name in C++? again.

Making an alias can be done using:

constexpr auto get_colour = get_color;
// or
constexpr auto get_colour(get_color);
const auto get_colour = get_color;
// or
const auto get_colour(get_color);

The advantage over:

auto get_colour = get_color;
// OR
auto get_colour(get_color);

is that the compiler will know for the constexpr/const version that get_colour won't change, so it can directly map the get_colour call to get_color. For the none constexpr version you will have an indirection over the stored pointer.

If you have

#include <iostream>
#include <string>

std::string get_color()
{
    return "green";
}

auto get_colour = get_color;

int main() {
  std::cout << get_colour() << "\n";
}

You can see that at the [QWORD PTR get_colour[abi:cxx11][rip]] that the is not inlined, because get_colour could changed:

get_color[abi:cxx11]():
        lea     rdx, [rdi+16]
        mov     BYTE PTR [rdi+20], 110
        mov     rax, rdi
        mov     QWORD PTR [rdi], rdx
        mov     DWORD PTR [rdi+16], 1701147239
        mov     QWORD PTR [rdi+8], 5
        mov     BYTE PTR [rdi+21], 0
        ret
.LC0:
        .string "\n"
main:
        push    rbp
        sub     rsp, 32
        mov     rdi, rsp
        call    [QWORD PTR get_colour[abi:cxx11][rip]]
        mov     rdx, QWORD PTR [rsp+8]
        mov     rsi, QWORD PTR [rsp]
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     rdi, rax
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC0
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     rdi, QWORD PTR [rsp]
        lea     rax, [rsp+16]
        cmp     rdi, rax
        je      .L8
        call    operator delete(void*)

But for the constexpr version:

#include <iostream>
#include <string>

std::string get_color()
{
    return "green";
}

constexpr auto get_colour = get_color;

int main() {
  std::cout << get_colour() << "\n";
}

The function call to get_colour can be inlined (get_color[abi:cxx11]() is not called) but the generated code directly appears in main::

get_color[abi:cxx11]():
        lea     rdx, [rdi+16]
        mov     BYTE PTR [rdi+20], 110
        mov     rax, rdi
        mov     QWORD PTR [rdi], rdx
        mov     DWORD PTR [rdi+16], 1701147239
        mov     QWORD PTR [rdi+8], 5
        mov     BYTE PTR [rdi+21], 0
        ret
.LC0:
        .string "\n"
main:
        push    rbp
        mov     edx, 5
        mov     edi, OFFSET FLAT:_ZSt4cout
        push    rbx
        sub     rsp, 40
        lea     rbx, [rsp+16]
        mov     BYTE PTR [rsp+20], 110
        mov     rsi, rbx
        mov     QWORD PTR [rsp], rbx
        mov     DWORD PTR [rsp+16], 1701147239
        mov     QWORD PTR [rsp+8], 5
        mov     BYTE PTR [rsp+21], 0
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     rdi, rax
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC0
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     rdi, QWORD PTR [rsp]
        cmp     rdi, rbx
        je      .L8
        call    operator delete(void*)

Or use perfect forwarding which will work for both free and member functions:

void get_color() {
}

template <typename... Args>
auto get_colour(Args&&... args) {
  return get_color(std::forward<Args>(args)...);
}

For c++11 -> decltype(get_color(std::forward<Args>(args)...)) needs to be added:

template <typename... Args>
auto get_colour(Args&&... args) -> decltype(get_color(std::forward<Args>(args)...)) {
  return get_color(std::forward<Args>(args)...);
}
t.niese
  • 39,256
  • 9
  • 74
  • 101
  • @caelras there the only way is IMHO perfect forwarding [as described here](https://stackoverflow.com/a/9864472). – t.niese Sep 04 '20 at 14:20
0

In cpp11 you can use the functional standard library, this fulfils your requirement

#include <functional>
#include <iostream>
#include<string>

    std::string func()
    {
    return "hello";
    }
    
    int main()
    {
    std::function<std::string()> newfunc = func;
    
    std::cout << newfunc() << std::endl;
    
    return 0;
    }

For more info have a look here

Galilean
  • 246
  • 4
  • 15
  • That does not really create an alias, and is bad for regarding optimization. But most importantly if fails the requirement of the OP: `but this can get very tricky to maintain. Is there any other way to give a second name to a function?` and `whenever you want to change the function parameters, you will have to change the first function and the second` in case the signature of `func` changes. – t.niese Sep 04 '20 at 14:23
0

You can also use reference variable.

std::string get_color(){
    return "green";
}

auto & get_colour = get_color;

Omkar76
  • 1,317
  • 1
  • 8
  • 22
0

This what I ended up doing:

template<typename... Args>
auto get_colour(Args&&... args)
{
  return get_color(static_cast<Args>(args)...);
}

Note: This only works with C++ 14 or higher