2012-03-03 73 views
3

我有一个(免费)函数模板,看起来像这样专业生产与模板

template <typename T> 
T get(); 

我现在要专注这个功能的一类,这本身就是一个模板,模板。但是我的编译器不想编译它,现在我问的是否可能,以及我如何实现它。只是为理念,代码可能看起来如下:(不编译)

template <> 
template <typename T> 
foo_type<T> get<foo_type<T>>() 

回答

3

你在做什么叫做部分专业化功能模板。但是部分功能模板的专门化是不允许的。函数模板的重载是允许的,但在这种情况下也是不可能的,因为函数只有返回类型,并且不允许重载类型的重载。

因此,解决办法是这样的:

namespace details 
{ 
    template <typename T> 
    struct worker 
    { 
     static T get(); 
    }; 

    template <typename T> //partial specialization of class is allowed 
    struct worker<foo<T>> 
    { 
     static foo<T> get(); 
    }; 

} 

template <typename T> 
T get() 
{ 
    return details::worker<T>::get(); 
} 

你也可以使用重载如果定义他们采取一个参数,从而使超载有效:

namespace details 
{ 
    template <typename T> 
    static T get(T*); 

    template <typename T> 
    static foo<T> get(foo<T>*); //now the overload is valid 

} 

template <typename T> 
T get() 
{ 
    return details::get<T>(static_cast<T*>(0)); 
} 

注意,参数static_cast<T*>(0)用于帮助编译器选择正确的过载。如果Tfoo<U>其它,则第一过载将被选择为传递给它的参数的类型将是T*而不是foo<U>*。如果Tfoo<U>,那么第二个重载将由编译器选择,因为它是更多专用的,并且可以接受在此情况下传递给它的参数,即foo<U>*

+0

现在,看到解决方案,这是显而易见的痛苦。谢谢!但现在我得到一个链接器错误..任何想法? – cooky451 2012-03-03 01:45:06

+0

错误,基于返回类型的重载不起作用... – Xeo 2012-03-03 01:45:15

+0

@Xeo:糟糕。是。你是对的。当我发布它时,我觉得我做错了什么,但是搞不清楚。 – Nawaz 2012-03-03 01:46:50

2

正如纳瓦兹表示,该标准只是不允许你这样做。但是,您可以将实现提取到类的静态方法中,并部分专门化该类。

template<class T> 
struct get_impl{ 
    static T get(){ ... } 
}; 

template<class T> 
struct get_impl<foo_type<T> >{ 
    static foo_type<T> get(){ ... } 
}; 

template<class T> 
T get(){ return get_impl<T>::get(); }