2013-05-11 13 views
8

Pisanie ogólnej minimalnej funkcji, Dwa pytania przyszły mi do głowy. Kod działa poprawnie z wszelkiego rodzaju wejściowego i różnej liczbie argumentów:Ogólne min i maks. - C++

namespace xyz 
{ 

template <typename T1, typename T2> 
auto min(const T1 &a, const T2 &b) -> decltype(a+b) 
{ 
    return a < b ? a : b; 
} 

template <typename T1, typename T2, typename ... Args> 
auto min(const T1 &a, const T2 &b, Args ... args) -> decltype(a+b) 
{ 
    return min(min(a, b), args...); 
} 

} 

int main() 
{ 
    cout << xyz::min(4, 5.8f, 3, 1.8, 3, 1.1, 9) << endl; 
    //     ^ ^  ^
    //     |  |   | 
    //     float double  int 
} 

 

  • Czy istnieje lepszy zamiennik decltype(a+b)? Sądzę, że istnieje standardowa klasa, której nie pamiętam, coś w rodzaju decltype(std::THE_RESULT<a,b>::type).

  • Zwrócony typ tego decltype(std::THE_RESULT<a,b>::type) to const & czy nie?

+1

Wydaje się dziwne mi się, że pozwalasz aib być różnych typów. To otwiera drzwi do wszelkiego rodzaju bezsensownych porównań, takich jak 'min (42," trzy ")'. Dlaczego nie wymagać, aby oba parametry (i wartość zwracana) były tego samego typu? –

+1

@AdrianMcCarthy: _ "W przypadku typów arytmetycznych typ wspólny może być również postrzegany jako typ wyrażenia arytmetycznego (prawdopodobnie w trybie mieszanym), takiego jak T0() + T1() + ... + Tn()" _. Tak więc myślę, że nie wolno używać 'min (42," trzy ")'. Powoduje błąd kompilacji. – deepmax

+0

Nawiasem mówiąc, istnieje artykuł o odtwarzaniu dobrych części makr wersji przy użyciu szablonów. Zaskakująco wiele do zrobienia. – chris

Odpowiedz

13

std::common_type (c++11):

Dla niewyspecjalizowanych std::common_type, zasad ustalania wspólny typ pomiędzy każdą parą T1, T2 są dokładnie zasady określające rodzaj Powrót trójargumentowy operator warunkowy, gdzie T1 i T2 są typami drugiego i trzeciego argumentu operacji.

i

Dla arytmetycznych rodzajów, wspólny typ może również być postrzegane jako rodzaj z (ewentualnie trybu mieszanego) wyrażenia arytmetycznego, takich jak T0() + T1() + ... + Tn().

Nie jestem pewien const&, ale można grać z std::remove_cv i std::remove_reference (i std::is_reference, aby znaleźć odpowiedź).

W rzeczywistości, here's lista narzędzi wsparcia typu. Puść się.

+0

Dzięki ... Dodałem trzecie powiązane pytanie. Czy mógłbyś na to spojrzeć? – deepmax

+2

@MM.To zadziała, ale nie jest całkowicie tym, co chcesz, myślę. Dla '(1,2,1.1)', które zwróci 'int'. 'decltype (min (1, 2))'. Możesz spróbować objąć całą rzecz, jak np. 'Decltype (min (min (a, b), args ...))' ale to nie działa z 'gcc' właśnie teraz. Myślę, że to błąd. – stardust

+0

@Nazwa: Tak, przetestowałem to i masz rację. – deepmax

5

Po odpowiedź i wartych uwagi Zrobiłem to jak poniżej:

template <typename T1, typename T2> 
auto min(const T1 &a, const T2 &b) 
-> typename std::common_type<const T1&, const T2&>::type 
{ 
    return a < b ? a : b; 
} 

template <typename T1, typename T2, typename ... Args> 
auto min(const T1 &a, const T2 &b, const Args& ... args) 
-> typename std::common_type<const T1&, const T2&, const Args& ...>::type 
{ 
    return min(min(a, b), args...); 
} 
Powiązane problemy