c++模板方法专门化以返回指针或引用



我有这个方法

template <typename T>
T GetFnInput(){
  //.... here is obtained void * t value from some library
  return (T)(t);
}

对于不同的类型,我有几个模板特殊化

template <>
uint32 GetFnInput<uint32>(){
    return 0;
}
template <>
bool GetFnInput<bool>(){
    return true;
}

但是,我需要一个专门化作为参考。我已经尝试了这个(代码是混乱的,不应该在生产中使用,这只是为了我的测试目的):

template <typename T, 
typename BaseT = std::decay<T>::type,
typename std::enable_if <std::is_reference<T>::value == true>::type* = nullptr >
T GetFnInput(){
  BaseT * t = new BaseT();
  return *t;
}

加上我把typename std::enable_if <std::is_reference<T>::value == false>::type* = nullptr >加到原来的(上面的)GetFnInput()但是它不能编译,以错误结束:

错误C2244: 'GetFnInput':无法匹配函数定义现有的声明

第一个问题是你在这里缺少typename:

typename BaseT = std::decay<T>::type,
                ^^^

一旦你有了这个,你就有了第二个问题,那就是对GetFnInput<int&>()的调用在原始函数模板GetFnInput<typename>和这个新函数模板GetFnInput<typename, typename, typename>之间是不明确的。这两个函数模板是相互重载的,在其他方面是不相关的。

通常你想做的是将模板形参提升到实参列表中,这样就更容易重载:

template <class T> struct tag { using type = T; };
template <class T>
auto get() -> decltype(get_impl(tag<T>{}))
{
    return get_impl(tag<T>{});
}

然后你可以更容易地编写get_impl函数模板。特定类型只是特定的重载:

uint32_t get_impl(tag<uint32_t> ) { return 0; }

和引用类型只是一个模板:

template <class T>
T& get_impl(tag<T& > ) { ???; }

请注意,返回对已分配指针的引用听起来确实是个坏主意。

您尝试的是重载,而不是专门化。由于function不能部分特化,我建议使用struct来代替:

template <typename T>
struct helper
{
    T operator() const { return {}; }
};
template <>
struct helper<bool>
{
    bool operator() const { return true; }
};
template <typename T>
struct helper<T&>
{
    T& operator() const { static T t; return t; }
};
template <typename T>
T GetFnInput(){
    return helper<T>{}();
}

最新更新