function specialization based on if template parameter is shared_ptr

c++, c++11, templates

Solution

Any reason not to simply use partial specialization?

#include <type_traits>
#include <memory>
#include <cstdio>

class Foo { };
typedef std::shared_ptr<Foo> SharedFoo;

template <class T>
struct getValue {
    getValue() {
        printf("not shared!\n");
    }
};

template <class T>
struct getValue<std::shared_ptr<T> > {
    getValue() {
        printf("shared!\n");
    }
};

int main(int, char **)
{
    getValue<SharedFoo>();
    getValue<Foo>();
    return 0;
}

Problem

I'm trying to detect if a type is a `shared_ptr<T>` and if it is, dispatch to a specific function template or override. Here's a simplified version of what I'm actually attempting: ``` #include <type_traits> #include <memory> #include <cstdio> template <class T> struct is_shared_ptr : std::false_type {}; template <class T> struct is_shared_ptr<std::shared_ptr<T> > : std::true_type {}; class Foo { }; typedef std::shared_ptr<Foo> SharedFoo; template<class T> void getValue(); template<class T, typename std::enable_if<is_shared_ptr<T>::value>::type = 0> void getValue() { printf("shared!\n"); } template<class T, typename std::enable_if<!is_shared_ptr<T>::value>::type = 0> void getValue() { printf("not shared!\n"); } int main(int, char **) { getValue<SharedFoo>(); getValue<Foo>(); return 0; } ``` It compiles just fine, but it seems the actual functions were never actually generated because the code doesn't link with the following errors: ``` /tmp/ccjAKSBE.o: In function `main': shared_test.cpp:(.text+0x10): undefined reference to `void getValue<std::shared_ptr<Foo>>()' shared_test.cpp:(.text+0x15): undefined reference to `void getValue<Foo>()' collect2: error: ld returned 1 exit status ``` I would think that those would be covered by the two function templates. But they aren't. Given that, it seems I am seriously misunderstanding something. So maybe it would help if I explain what I'm /trying/ to do rather than what I'm actually doing. I have some "magic" code using a bunch of new (to me) C++11 features to bind C++ code to lua (can be seen here: https://github.com/Tomasu/LuaGlue). someone has recently asked for support for binding to classes wrapped in `shared_ptr`'s. which is not something that works at the moment, because it binds at compile time using templates and tuple unwrapping to generate code to call functions on either the C++ or lua side. In the "magic" unwrapping code, I have a bunch of overridden and "specialized" functions that handle various variable types. Some for basic types, one for static objects, and another for pointer to objects. A `shared_ptr` can't be handled in the same way as either a static or pointer object, so I need to add some extra handling just for them. For example: ``` template<typename T> T getValue(LuaGlue &, lua_State *, unsigned int); template<> int getValue<int>(LuaGlue &, lua_State *state, unsigned int idx) { return luaL_checkint(state, idx); } template<class T> T getValue(LuaGlue &g, lua_State *state, unsigned int idx) { return getValue_<T>(g, state, idx, std::is_pointer<T>()); } ``` That's the actual code (notice the hairy template/override via function argument :-x). I had thought it'd be as simple as adding another `addValue` function, along the lines of the code in my earlier example, via `enable_if`.

Original source