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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With