2012-01-18 14 views
5

UWAGA: To pytanie jest tylko luźno związane z tinyxml, jednak takie szczegóły mogą pomóc lepiej zilustrować tę koncepcję.Specjalizacja szablonu funkcji w innej klasie/przestrzeni nazw?

Napisałem szablon funkcji, który będzie iterować przez nadrzędne węzły XML węzłów XML, pobrać wartość elementu podrzędnego, a następnie przesłać tę wartość elementu potomnego do wektora.

The „pobrać wartość” część jest również zapisana jako szablon funkcji:

tj

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

Są specjalizacje do odzyskiwania części, do powrotu różne rodzaje wartości, na przykład element podrzędny std :: string i inne niestandardowe obiekty.

tj

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

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

To wszystko działa doskonale, jednak uderzyło mnie, że byłoby to bardzo przydatne w udostępnionej biblioteki funkcji gdy ma do czynienia z plikami TinyXML.

Pytanie: Czy można zadeklarować szablon funkcji w jednym obszarze nazw, np. namespace UtilityFunctions, która nie ma żadnej wiedzy na temat konkretnych typów obiektów, takich jak 'MyObject', a następnie deklaruje i definiuje specjalizacje tego szablonu funkcji w innych obszarach nazw, które mają wiedzę na temat określonych typów obiektów, takich jak 'MyObject'?

Moje przeczucie polega na tym, że nie jest to możliwe, ale koncepcja posiadania wspólnego szablonu funkcji wydaje mi się wystarczająco przydatna, aby znaleźć alternatywny sposób zbliżenia się do funkcjonalności, której szukam. ..

Przeprasza, jeśli któraś z terminów jest niepoprawna lub wyjaśnienie jest niejasne. Zrobiłem dużo badań wokół tego tematu (aby przejść do punktu pracy nad specjalizacją szablonu funkcji w obrębie tej samej przestrzeni nazw), ale nie znalazłem jeszcze ostatecznej odpowiedzi.

+1

Można po prostu użyć przeciążenia funkcji ... Zwrócić bool lub kod błędu i przekazać parametr out przez odniesienie. – AJG85

+0

Tak, to byłoby o wiele łatwiejsze :) –

+0

[Ten artykuł autorstwa Herb Sutter] (http://www.gotw.ca/publications/mill17.htm) na temat specjalizacji funkcji może cię kołysać ;-) – AJG85

Odpowiedz

3

Nie jest możliwe napisanie w jednej przestrzeni nazw specjalizacja szablonu zdefiniowane w innej przestrzeni nazw (ponieważ nie byłoby specjalizacja tego szablonu, który zdefiniowano w innej przestrzeni nazw to byłby inny szablon).

Jednak jest całkowicie dopuszczalne rozszerzanie przestrzeni nazw, w której pierwotnie zdefiniowano szablon, zapisując swoją specjalizację w całkowicie oddzielnym pliku źródłowym.

Więc tutaj jest to, co nie może zrobić:

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

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

można zobaczyć piękny komunikat o błędzie na powyższe na 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;} 
         ^

Oto co może zrobić:

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

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

Czy jest jakiś powód, dla którego to byłby problem?

Ponadto, jeśli delegujesz pracę do funkcji związanej z czytanym obiektem (członkiem lub funkcją bezpłatną), możesz polegać na tej funkcji znalezionej przez ADL i wywołanej. Oznacza to, że powinieneś być w stanie zminimalizować ilość takich specjalizacji jak wyżej.

Oto przykład:

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; 
} 

Zmieniano dodać przykład

+0

+1 bardzo ładne, a ciepłe powitanie na forum społeczności SO C++ :) –

1

Chodzi o to, "Każda deklaracja dla szablonu musi znajdować się w tej samej przestrzeni nazw, tak jak powtarzane deklaracje każda inna nazwa obiektu "

deklaracja/zdefiniowanie go w innym obszarze nazw jest nieważna, , aby uzyskać więcej informacji, przejdź do punktu 12 w FAQ

Powiązane problemy