1

I was trying a new approach to the answer I gave to this question, I thought that returning the address of a member function as ID could be a path worth to explore:

struct S
{
    template <typename T>
    void f(){};

    using mp = void(S::*)();

    template <typename T>
    static constexpr mp ID()
    {
        return &S::f<T>;
    }
};

I thought that every instantiation of S::f would have an unique address which will be shared in every translation unit and even might be available at compile time, so I tested it:

std::cout << S::ID<char>() << '\n';

And the output was 1; quite unexpected to be honest (I was expecting the value to be printed as an hex number, like other pointers), but moving forward I tried other types:

std::cout << S::ID<char>() << '\n';  // Prints '1'.
std::cout << S::ID<char>() << '\n';  // Expecting '1', got '1'.
std::cout << S::ID<short>() << '\n'; // Execting something different to '1', got '1'.

At this point, I realized that the 1 value wasn't the "adress of the member function inside the object" because two different functions (void S::f<char>() and void S::f<short>()) shared the same address. So I've tried another approach:

struct S
{
    template <typename T>
    static auto ID()
    {
        return +[]{};
    }
};

Captureless lambdas can be converted to function pointers and each lambda has an unique type even if its contents are the same, so I was expecting some random-ish values but got 1 again:

std::cout << S::ID<char>() << '\n';  // Expecting '0x????????' Prints '1'.
std::cout << S::ID<char>() << '\n';  // Expecting '0x????????' Prints '1'.
std::cout << S::ID<short>() << '\n'; // Expecting '0x!!!!!!!!' Prints '1'.

At this point, I just want to know what those 1 means and why are all of them 1 even if the expected behaviour is that all of them must yield a different value.

PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94
  • 1
    `1` is a `bool`... – BoBTFish May 28 '19 at 10:41
  • So, it is entering through the `ostream operator<<(ostream &, bool)`?! – PaperBirdMaster May 28 '19 at 10:43
  • The reference will tell you that pointers to functions and to members are cast to `bool` rather than `void*`, and that is what you are seeing. – Gem Taylor May 28 '19 at 10:45
  • Yes, and this is because there are no implicit conversions to `void*` from a pointer to (member) function like there are from a pointer to object. – aschepler May 28 '19 at 10:45
  • Pointer to member is not a simple "pointer" type. It may be an index into the vtable, or it may be a pointer to the actual function instance. It may have to handle virtual inheritance, and a few other nasties, so it has a number of fields. – Gem Taylor May 28 '19 at 10:46
  • 1
    To confirm, you could try doing `std::cout << std::boolalpha` before other prints, and you should see "true" (or possibly a translation) instead of "1". – aschepler May 28 '19 at 10:47

0 Answers0