c++c++14static-polymorphism

How can I use static polymorphism to convert between int and pointer types?


I have this piece of code:

#include <iostream>

template<class T> void* ToPtr(T t) { return ToPtr((void*)t); }
void* ToPtr(void* i) { return i; }
void* ToPtr(int i) { return (void*)(long)(unsigned int)i; }

template<class T> int ToInt(T t) { return ToInt((void*)t); }
int ToInt(void* i) { return (int)(unsigned int)(long)i; }
int ToInt(int i) { return i; }

struct MyClass {
  template<class T>
  void* Find(T t) { return ToPtr(t); }

  template<class T>
  int FindInt(T t) { return ToInt(t); }
};

int main() {
  MyClass myClass;
  int myInt = 1;
  std::cout << &myClass << std::endl;
  std::cout << myInt << std::endl;
  std::cout << myClass.Find(&myClass) << std::endl;
  std::cout << myClass.Find(myInt) << std::endl;
  std::cout << myClass.FindInt(&myClass) << std::endl;
  std::cout << myClass.FindInt(myInt) << std::endl;
}

The program crashes in the first call to Find() but I'm not sure why. I'm using GCC 6.2.0, which is only C++14 compliant, otherwise I'd use constexpr. What am I doing wrong?


Solution

  • template<class T> void* ToPtr(T t) { return ToPtr((void*)t); }
    

    This calls itself. Forever.

    Since non-templates are preferred over templates, this is really easy to fix: you just have to put the non-templates first so that they're in scope within the overload above:

    void* ToPtr(void* i) { return i; }
    void* ToPtr(int i) { return (void*)(long)(unsigned int)i; }
    template<class T> void* ToPtr(T t) { return ToPtr((void*)t); }
    
    int ToInt(void* i) { return (int)(unsigned int)(long)i; }
    int ToInt(int i) { return i; }
    template<class T> int ToInt(T t) { return ToInt((void*)t); }
    

    (live demo)

    When your program "crashes", you should be running it in a debugger. You'd have seen the stack overflow quite clearly, as hundreds of stack frames would all show the same recursive call.