我正在尝试检测某个类型是否为shared_ptr<T>
,如果是,则调度到特定的函数模板或覆盖。
这是我实际尝试的简化版本:
#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;
}
它编译得很好,但似乎实际的函数从未实际生成,因为代码没有链接以下错误:
/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
我认为这些将由两个功能模板涵盖。但他们不是。
鉴于此,我似乎误解了一些事情。
所以,如果我解释一下我正在做什么/尝试做什么而不是我实际做的事情,这可能会有所帮助。
我有一些“魔术”代码使用一堆新的(对我来说)C ++ 11特性来将C ++代码绑定到lua(可以在这里看到:https://github.com/Tomasu/LuaGlue)。有人最近要求支持绑定shared_ptr
中包含的类。这不是目前可用的东西,因为它在编译时使用模板和元组解包绑定生成代码以在C ++或lua端调用函数。在“神奇”的展开代码中,我有一堆被覆盖的“专用”函数来处理各种变量类型。一些用于基本类型,一个用于静态对象,另一个用于指向对象。 shared_ptr
无法以与静态或指针对象相同的方式处理,因此我需要为它们添加一些额外的处理。
例如:
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>());
}
这是实际的代码(通过函数参数注意毛茸茸的模板/覆盖:-x)。
我原以为它就像在前面的例子中通过addValue
添加另一个enable_if
函数一样简单。
答案 0 :(得分:5)
任何不使用部分专业化的理由?
#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;
}
答案 1 :(得分:2)
您的程序声明template<class T> void getValue()
但未定义它。 template <typename, typename> void getValue()
是一个不同的功能。编译器选择template<class T> void getValue()
作为与您的调用更好的匹配,当然在链接时失败,因为没有该函数的定义。
我更喜欢标签发送的简单性(适用于live at Coliru):
template<class T>
void getValue(std::true_type)
{
printf("shared!\n");
}
template<class T>
void getValue(std::false_type)
{
printf("not shared!\n");
}
template<class T>
void getValue() {
return getValue<T>(is_shared_ptr<T>{});
}
答案 2 :(得分:0)
这是另一个解决方案,它基本上是对OP而不是替代方案的修复(使用类及其构造函数,如zennehoy的post或标签分派,如Casey's)。
// Do not provide this declaration:
// template<class T> void getValue();
template<class T>
typename std::enable_if<is_shared_ptr<T>::value>::type
getValue()
{
printf("shared!\n");
}
template<class T>
typename std::enable_if<!is_shared_ptr<T>::value>::type
getValue()
{
printf("not shared!\n");
}
我必须说,正如Casey所说,我也“更喜欢标签发送的简单性”。因此,我会寻求他的解决方案。
我也发现zennehoy的想法很有趣,但不幸的是,它不允许你的函数返回一些东西。 (我相信解决方法是可行的,但会增加复杂性。)在这里使用解决方案,您只需要提供返回类型作为std::enable_if
的第二个参数。