要求函数模板的返回类型为模板的特化

时间:2010-09-17 05:15:00

标签: c++ gcc

我已经在stackoverflow上讨论了一段时间,但要么我不理解模板足以找到解决方案,要么之前没有得到解答。

在这个例子中:

template <typename T> T f();

是否可以使函数要求类型T成为std::basic_string模板的特化?

我可以将模板定义为T std::basic_string的类型(当然在内部使用std::basic_string<T>):

template <typename T> std::basic_string<T> f();

但是我无法将std::stringstd::wstring传递给函数(期望返回类型分别为std::stringstd::wstring),这是这里真正的目标(能够传递任何来自std::basic_string模板的类型)。

3 个答案:

答案 0 :(得分:8)

部分特化允许您测试类型是否是特定模板的特化。 SFINAE是一个可以“关闭”功能模板声明的技巧。该解决方案结合了这些技术。

template< typename T > // by default,
struct enable_if_basic_string {}; // a type is not a basic_string

template< typename CharT, typename Traits >
struct enable_if_basic_string< basic_string< CharT, Traits > > {
    typedef basic_string< CharT, Traits > type; // same as argument type
};

// enable_if_basic_string<>::type exists only if T specializes basic_string
// if not, compiler ignores function declaration per SFINAE.
template< typename T >
typename enable_if_basic_string< T >::type
F() {
    .....
}

如果您的意思是派生和专业化,您也可以查看std::tr1::is_convertibleenable_if

答案 1 :(得分:5)

不要求T成为std::basic_string的专业化,为什么不只是假设 Tstd::basic_string的专业化并让模板实例化如果不是则失败。只需使用您需要的std::basic_string内容即可。

例如,

template <typename T>
T get_first_three_chars(const T& str) { return str.substr(0, 3); }

在此,我们假设T具有成员函数substr;如果没有,则实例化将失败,从而导致编译错误。

答案 2 :(得分:1)

这在vanilla C ++中是不可能的。为C ++ 0x提出了一种语言结构,允许这样做,不幸的是它被删除了。

您可以使用Boost概念检查库在某种程度上执行此操作,但是:http://www.boost.org/doc/libs/1_44_0/libs/concept_check/concept_check.htm