我有一个模板包装函数,它返回一个这样的值:
template<class T>
T foo(Bar& bar, const char* key) {
return bar.value<T>(key);
}
但是我想让它处理指针类型有点不同,比如:
template<class T>
T foo(Bar& bar, const char* key) {
return (T)bar.value<void*>(key);
}
所以我可以这样做:
int x = foo<int>(bar, "x");
Baz* b = foo<Baz*>(bar, "b");
如上所述写它显然会因为多个定义而给我一个错误。有没有其他方法可以做到这一点?我宁愿不为每个使用指针的函数添加一个强制转换。
我尝试过以下方法:
template<class T>
T foo(Bar& bar, const char* key) {
if(std::is_pointer<T>::value)
return (T)bar.value<void*>(key);
else
return bar.value<T>(key);
}
但是这不起作用,因为涉及QVariants并且它们通过仅使用未知指针类型(bar.value<T>
)实例化其模板函数来产生错误。
答案 0 :(得分:12)
使用标记分派将调用委托给辅助函数,这些函数根据T
是否为指针类型执行不同的操作。
namespace detail
{
template<class T>
T foo(Bar& bar, const char* key, std::false_type /*not is_pointer*/) {
return bar.value<T>(key);
}
template<class T>
T foo(Bar& bar, const char* key, std::true_type /*is_pointer*/) {
return (T)bar.value<void*>(key);
}
}
template<class T>
T foo(Bar& bar, const char* key) {
return detail::foo<T>(bar, key, std::is_pointer<T>{});
}
答案 1 :(得分:8)
功能的部分专业化不是语言的一部分。
你可以举例如:
使用SFINAE。
template<class T>
typename std::enable_if<std::is_pointer<T>::value, T>::type
foo(Bar& bar, const char* key) {return (T)bar.value<void*>(key);}
template<class T>
typename std::enable_if<!std::is_pointer<T>::value, T>::type
foo(Bar& bar, const char* key) {return bar.value<T>(key);}