我已经在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::string
或std::wstring
传递给函数(期望返回类型分别为std::string
和std::wstring
),这是这里真正的目标(能够传递任何来自std::basic_string
模板的类型)。
答案 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_convertible
和enable_if
。
答案 1 :(得分:5)
不要求T
成为std::basic_string
的专业化,为什么不只是假设 T
是std::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