2012-01-18 62 views
5

注:这个问题只与tinyxml松散相关,但包括这样的细节可能有助于更好地说明这个概念。函数模板在另一个类/名称空间中的专门化?

我写了一个函数模板,它将遍历父XML节点子元素,检索子元素的值,然后将该子元素值推送到一个向量。

在“检索值”部分也被写入作为一个函数的模板:

template <typename Type> 
Type getXmlCollectionItem(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent); 

存在用于检索部特殊化,用于返回不同类型的子元素值,例如的std :: string和其他自定义对象。

template <> 
std::string getXmlCollectionItem<std::string>(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent); 

template <> 
MyObject getXmlCollectionItem<MyObject>(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent); 

这一切都工作得很好,但它让我吃惊的是,这将是与TinyXML的文件打交道时,有一个共享的函数库是非常有用的。

问题:是否可以在一个命名空间中声明函数模板,例如namespace UtilityFunctions,它不具有'MyObject'等特定对象类型的任何知识,然后在具有特定对象类型知识的其他名称空间中声明和定义该函数模板的特化,例如'MyObject'

我的预感是,这是不可能的,但有一个共同的功能模板的概念似乎对我来说足够有用,因为那里有一个接近我正在寻找的功能的替代方法。 ..

道歉,如果任何术语不正确或解释不清楚。我围绕这个话题做了大量的研究(为了在相同的命名空间中找到工作函数模板专门化的观点),但还没有找到明确的答案。

+1

您可以使用函数重载...返回布尔或错误代码并通过引用传递出参数。 – AJG85 2012-01-18 15:25:35

+0

是的,这将是更容易:) – 2012-01-18 15:28:36

+0

[本文由Herb萨特](http://www.gotw.ca/publications/mill17.htm)功能专业化可能摇摆你;-) – AJG85 2012-01-18 15:42:28

回答

3

这是不可能写在一个名称空间模板的一个特例中另一个命名空间定义(因为这不会是模板的专业化,在另一个的名称空间被定义这将是一个不同的模板)。

然而,扩展最初定义模板的命名空间是完全可以的,在完全独立的源文件中编写专业化。

因此,这里是你无法做什么:

namespace A { namespace B { 
    template <typename T> int foo(T) {throw 1;} 
}} 

template <> int A::B::foo(int) {throw 0;} 

您可以在http://www.comeaucomputing.com/tryitout/

"ComeauTest.c", line 5: error: the initial explicit specialization of function 
      "A::B::foo(T) [with T=int]" must be declared in the namespace 
      containing the template 
    template <> int A::B::foo(int) {throw 0;} 
         ^

这里查看上述友好的错误消息是你可以做到:

namespace A { namespace B { 
    template <typename T> int foo(T) {throw 1;} 
}} 

namespace A { namespace B { 
    template <> int foo(int) {throw 0;} 
}} 

这有什么理由会成为一个问题吗?另外,如果您将工作委托给与正在阅读的对象(成员函数或自由函数)相关的函数,则可以依赖通过ADL找到的函数并调用该函数。意思是你应该能够减少像上面这样的专业化的数量。

这里是例子:

namespace A { namespace B { 
    template <typename T> int bar(T t) {return 0;} 
    template <typename T> int foo(T t) {return bar(t);} 
}} 

namespace C { 
    struct Bah {}; 
    int bar(Bah&) {return 1;} 
} 


int main(int argc,char** argv) 
{ 
    C::Bah bah; 

    std::cout << A::B::foo(0) << std::endl; 
    std::cout << A::B::foo(bah) << std::endl; 
} 

编辑添加一个例子这里

+0

+1非常好,一个热烈欢迎加入SO C++社区:) – 2012-01-18 16:04:21

1

点是“为模板的每份报关单,必须放置在同一个命名空间,任何其他的一样,反复声明命名实体“

声明/在不同命名空间中定义它是无效的, 有关更多信息,请通过中的第12个点