2010-09-17 62 views
1

我在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模板的任何类型)。

+0

@ splash请指出您是指“派生自”还是“专业化”。在你原来的帖子中你说过“源自”。 Potatoswatter将其标题改为“专业化”,但只留下了主要内容。你的真实意图是什么?请修复你的问题。你最后一段对我来说就像“我不能传递std :: string,因为它看起来像'std :: basic_string '。”。它不一定跟随你的正文,你的意思是什么。 – 2010-09-17 11:01:16

+0

如果我理解术语,我会用'专业化'。你甚至可以从模板类派生吗? – komiga 2010-09-17 12:00:53

+0

@ splash谢谢,现在很清楚。同理,我会解释“derived from basic_string”,因为这个类来自'basic_string '。所以从某种意义上说,它是不明确的:) – 2010-09-17 12:09:53

回答

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为好。

+0

+1 - 它绝对解决了这个问题。不幸的是,它也要求你用无用的参数来装饰函数,不过幸好可以用默认参数隐藏。 – Paul 2010-09-17 06:40:37

+0

@Paul:不,那里没有参数。我根本没有改变他的函数的模板或运行时参数。 – Potatoswatter 2010-09-17 06:48:15

+0

@Patatoswatter:是的,对于这个应用程序。当你已经有一个返回类型时,我指的是使用这个习惯用法。对不起,我不清楚。 – Paul 2010-09-17 06:54:11

1

这在vanilla C++中是不可能的。有一种针对C++ 0x的语言结构,可能会导致这种情况,不幸的是它被丢弃了。

你可以这样做在一定程度上与Boost概念检查库,但是:http://www.boost.org/doc/libs/1_44_0/libs/concept_check/concept_check.htm

+0

我不能评论詹姆斯麦克奈利斯的帖子,因为一些无用的声望要求,所以我会在这里说一下:我是堆栈溢出的新手,我在回答问题时通常会看到的一个趋势是实际上没有回答这个问题,但是却忽略了这个问题。这是堆栈溢出的正常情况吗,还是我只是决定在错误的时间加入? – Paul 2010-09-17 05:57:16

+0

邓诺。我经常不在这里。 我知道我永远不会使用Boost。你的回答确实回答了我的问题,但没有给我一个解决方案。 – komiga 2010-09-17 06:18:54

+0

是否有您选择不使用助推的特定原因,还是因工作原因而受到限制? 编辑:此外,在上面发布的注释代码中,请考虑尽可能使用引用,并且只有在需要特定功能时才会还原为指针。 – Paul 2010-09-17 06:21:43

5

而是要求Tstd::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;如果没有,那么实例化将失败,导致编译错误。

+0

嗯。这看起来如何? http://pastebin.com/xiL8TGSn 我认为我不应该使用字符串指针,但它会编译。编辑:划痕。这适用于我所需要的:http://pastebin.com/kptMXUPL 任何东西看起来都不对? – komiga 2010-09-17 06:16:18

+0

除了它是指针而不是引用,是..由于某种原因,我不能再编辑该评论,所以这里是我留下的:http://pastebin.com/6yQdTWYV – komiga 2010-09-17 06:31:44

+0

@ splash:你可以编辑评论仅限于5分钟的宽限期。 – sbi 2010-09-17 08:12:03