Search code examples
c++undefined-behavior

Do these inline functions cause undefined behavior


Foo1.hpp:

#pragma once

#include <string>

enum class Foo1 {
   A, B, C
};

// Commented out to avoid compiler error
//inline Foo1 fFromStr(const std::string& a) {
//    if (a == "A") return Foo1::A;
//    if (a == "B") return Foo1::B;
//    else          return Foo1::C;
//}

inline std::string fToStr(const Foo1 a) {
    switch (a) {
    case Foo1::A: return "A";
    case Foo1::B: return "B";
    default     : return "C";
    }
}

Foo2.hpp:

#pragma once

#include <string>

enum class Foo2 {
   A, B, C
};

// Commented out to avoid compiler error
//inline Foo2 fFromStr(const std::string& a) {
//    if (a == "A") return Foo2::A;
//    if (a == "B") return Foo2::B;
//    else          return Foo2::C;
//}

inline std::string fToStr(const Foo2 a) {
    switch (a) {
    case Foo2::A: return "A";
    case Foo2::B: return "B";
    default     : return "C";
    }
}

main.cpp:

#include "Foo1.hpp"
#include "Foo2.hpp"

int main() {
    fToStr(Foo1::A);
    //fFromStr("A");
    fToStr(Foo2::A);
    //fFromStr("A");
    return 0;
}

From what I have read online two global inline functions must have unique names to avoid undefined behavior. I believe the undefined behavior would come from the linker arbitrarily choosing one of the functions and removing the other

In the code above the two fFromStr cause a compiler error because they are ambiguous:

In file included from main.cpp:2:
Foo2.hpp:9:13: error: ambiguating new declaration of 'Foo2 fFromStr(const string&)'
    9 | inline Foo2 fFromStr(const std::string& a) {
      |             ^~~~~~~~
In file included from main.cpp:1:
Foo1.hpp:9:13: note: old declaration 'Foo1 fFromStr(const string&)'
    9 | inline Foo1 fFromStr(const std::string& a) {
      |

However fToStr does not cause a compiler error because its usage requires specifying Foo1 or Foo2

My question is whether the two fToStr cause undefined behavior or if their type requirements avoid an issue


Solution

  • whether the two fToStr cause undefined behavior or if their type requirements avoid an issue

    inline std::string fToStr(const Foo1 a)
    inline std::string fToStr(const Foo2 a)
    

    These are just bog-standard run-of-the-mill overloaded functions. There is nothing wrong with them whatsoever.