2012-03-09 26 views

Odpowiedz

15

C++ 03, specyfikacja wyraźnie zabrania domyślny argumentu przed użyciem wywnioskować argumentu szablonu (C++ 03 §14.8.2/17):

A template type-parameter cannot be deduced from the type of a function default argument.

C++ 11 , możesz podać domyślny argument szablonu dla szablonu funkcji:

template <typename T = float> 
void bar(int a, T b = 0.0f) { } 

Domyślny argument szablonu jest wymagany. Jeśli domyślny argument szablonu nie zostanie podany, domyślny argument funkcji nadal nie będzie można zastosować do odliczenia argumentu szablonu. W szczególności, stosuje się następujące (C++ 11 14.8.2.5/5)

The non-deduced contexts are:

...

  • A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.
+10

Mówiąc "Ponieważ standard tak mówi" jest poprawną odpowiedzią, dobrze byłoby poznać uzasadnienie stojące za tym. –

+1

Między innymi, różne deklaracje funkcji mogą zadeklarować różne domyślne argumenty (jestem prawie pewien, że to samo dotyczy szablonów funkcji). –

+1

@James: Nie, różne deklaracje nie mogą zadeklarować innych domyślnych argumentów. Nawet w przypadku wielu deklaracji nie można podać tego samego domyślnego argumentu. 8.3.6 mówi: "Domyślny argument nie zostanie przekreślony przez późniejszą deklarację (nawet o tej samej wartości)." Oczywiście dotyczy to tylko funkcji innych niż szablony. W przypadku funkcji szablonu wygląda na to, że domyślne argumenty można podać tylko w deklaracji początkowej. –

4

Głównym powodem może być to, że

void foo(bar, xyzzy = 0); 

jest podobny do pary przeciążenia.

void foo(bar b) { foo(b, 0); } 
foo(bar, xyzzy); 

Ponadto, czasami jest korzystne, byłaby go w taki:

void foo(bar b) { /* something other than foo(b, 0); */ } 
foo(bar, xyzzy); 

Nawet kiedy napisany jako jeden, to wciąż jak dwie funkcje w jednym, z których żadna nie jest „korzystne” w jakimkolwiek sensie . Nazywasz funkcję jednego argumentu; dwuargumentowy jest faktycznie inną funkcją. Domyślna notacja argumentu po prostu łączy je w jeden.

Jeśli przeciążenie miało mieć charakter, o który prosisz, to dla zachowania spójności musiałoby działać w przypadku, gdy szablon jest podzielony na dwie definicje. To nie miałoby sensu, ponieważ wtedy dedukcja byłaby ciągnięciem typów z niezwiązanej funkcji, która nie jest wywoływana! A jeśli nie zostało to zaimplementowane, oznaczałoby to, że przeciążenie różnych długości listy parametrów staje się "obywatelem drugiej kategorii" w porównaniu do "argumentowania domyślnego".

Dobrze, jeśli różnica między przeciążeniami a defaultingiem jest całkowicie ukryta dla klienta.

7

W tym celu wystąpiłyby pewne trudności techniczne. Pamiętaj, że domyślne argumenty w szablonach nie są tworzone, dopóki nie będą potrzebne. Rozważmy następnie:

template<typename T, typename U> void f(U p = T::g()); // (A) 
template<typename T> T f(long, int = T()); // (B) 
int r = f<int>(1); 

ten został rozwiązany dzisiaj wykonując (między innymi) w następujących etapach:

  1. próbę wyprowadzić parametrów szablonu dla kandydatów (A) i (B); to się nie udaje (A), dlatego jest eliminowane.
  2. wykonać rozdzielczość przeciążania; (B) jest wybrany
  3. formularz połączenia, instancji domyślnej argumentu

W celu wyłonienia z domyślnym argumentem, że domyślnym argumentem musiałaby zostać sama instancja przed zakończeniem procesu dedukcji. To może zawieść, prowadząc do błędów spoza kontekstu SFINAE. Oznacza to, że kandydat, który może być całkowicie nieodpowiedni dla połączenia, może wywołać błąd.

+0

Brzmi sensownie dla mnie. –

Powiązane problemy