2012-11-15 21 views
7

Jak zainicjować zmienną statyczną dla częściowej specjalizacji?C++ Jak zainicjować zmienne statyczne częściowej specjalizacji szablonów

template <bool A=true, bool B=false> 
struct from { 
    const static std::string value; 
}; 

// no specialization - works 
template <bool A, bool B> 
const std::string from<A, B>::value = ""; 

// partial specialization - does not compile - 
// Error: template argument list following class template name must list parameters in the order used in template parameter list 
// Error: from<A,B>' : too few template arguments 
template <bool B> 
const std::string from<true, B>::value = ""; 

// full specialization - works 
const std::string from<false, true>::value = ""; 

Dlaczego częściowa praca nie działa?

EDIT: Znalazłem rozwiązanie oparte na Partial template specialization for initialization of static data members of template classes

muszę powtórzyć deklaracji dla częściowej specjalizacji zanim pozwolił mi zainicjować zmienną statyczną:

template <bool B> 
struct from<true, B> { 
    const static std::string value; 
}; 

Ponownie, pytanie brzmi, dlaczego ?

+0

Który kompilator? W [g ++ 4.3.4] (http://ideone.com/jM6sIb), ostatni też nie działa. – didierc

+0

Czy nie musisz także specjalizować całego szablonu zajęć? Myślę, że dla członków dozwolona jest tylko jawna (= pełna) specjalizacja. –

+0

kompilator był VS2010 –

Odpowiedz

3

Częściowa specjalizacja członków (bez względu na to, czy są funkcjami, czy statycznymi danymi) jest niedozwolona bez częściowej specjalizacji dołączania samego szablonu klasy.

Oznacza to, że musisz specjalizować szablon klasy również. Więc następujące powinny działać:

//partial specialization of class template 
template <bool B> 
struct from<true, B> { 
    const static std::string value; 
}; 

//now you can do this!  
template <bool B> 
const std::string from<true, B>::value = "" 

Ponadto, nie będzie to skompilować (próbowałeś kompilacji jest?):

// full specialization - works (SORRY, IT WILL NOT WORK!) 
const std::string from<false, true>::value = ""; //this should be an error 

Masz napisać to:

// full specialization 
template<> //<---- this is important! 
const std::string from<false, true>::value = "" 
+0

Ok. Moim celem jest zastąpienie niektórych instrukcji if-the-else przez szablony. Widzę, że używanie zmiennych statycznych w tym konkretnym scenariuszu jest problematyczne. Czy poleciłbyś sposób na rozwiązanie tego problemu? Chciałbym wybrać ciąg na podstawie wartości parametrów szablonu. –

+0

pokonałeś mnie. – didierc

+0

@CandyChiu: Dlaczego zamiast tego nie użyjesz tablicy/mapy? Lub możesz użyć funkcji składowej w szablonie klasy, która zwróci inną wartość na podstawie wartości argumentów szablonu. – Nawaz

2

Oto działająca pełna specjalizacja szablonu.

#include <string> 
#include <iostream> 

template <bool A=true, bool B=false> 
struct from { 
    const static std::string value; 
}; 

// no specialization - works 
template <bool A, bool B> 
const std::string from<A, B>::value = "no specialization"; 

// full specialization, note the empty template parameter list 
template <> 
const std::string from<true, true>::value = "<true,true> specialization"; 


int main() { 
    std::cout << from<false, false>::value << std::endl; 
    std::cout << from<true, true>::value << std::endl; 
} 

Znalazłeś właściwy sposób definiowania częściowego.

Powód, dla którego nie działa część, polega na zadeklarowaniu typu struktury przed umożliwieniem inicjalizacji dla jej pola statycznego. Częściowa specjalizacja jest szablonem i zasługuje na definicję.

Pełna specjalizacja jest w rzeczywistości instancją typu początkowego szablonu, dlatego nie trzeba jej definiować osobno.

Powiązane problemy