2010-11-11 21 views
5

definiujemy niektóre wytyczne w stylu kodowania w C++ na podstawie these guidelines. Numer 8 mówi: "Nazwy reprezentujące typy szablonów powinny być pojedynczą wielką literą." Objaśnienie: "Wspólna praktyka w społeczności programistów języka C++ powoduje, że nazwy szablonów wyróżniają się względem wszystkich używanych nazw."Czy nazwy reprezentujące typy szablonów powinny być pojedynczymi znakami?

Czy to naprawdę takie powszechne? Zgadzam się, że ma sens mieć template<class T> class vector {...}. Ale co jeśli mam kilka argumentów za szablonem? Nie sądzę, że <class A, class B> jest łatwiejsze do zrozumienia niż .

Czy zgadzają się Państwo, że często zdarza się, że dana zasada nie powinna być stosowana (co jest dozwolone zgodnie z 1 ...)?

Dzięki za twoje myśli!

Odpowiedz

7

Naprawdę nie zgadzam się z tą konwencją nazewnictwa. Dla mnie parametry szablonu reprezentujące w pełni rodzajowy typ mają sens jako prosta litera - to jest typ T, naprawdę nie obchodzi mnie, który. Ale jeśli są jakieś wymagania co do typu, sensowne jest utworzenie nazwy, która identyfikuje to, co jest argumentem szablonu: template <typename T, typename Allocator> struct container - pierwszy typ jest ogólny, dowolny T zmieści się, ale drugi to alokator.

Nie inaczej jest z funkcjami, których nie chcą parametry nazywać a, b ... w kolejności lub wyglądu, lecz wytwarzają znaczących nazw jako część dokumentacji. Ponadto, jeśli opracowuję przewodnik stylu, rozważam wymaganie lokalnych typów argumentów szablonu w przypadku klas szablonów wraz z statycznymi twierdzeniami na temat wymagań dla typów (jeśli to możliwe). To znaczy, przynajmniej do pojęć zapewniających tę funkcjonalność.

Uważam, że STL jest dobrym przykładem biblioteki i widać, że generowanie pomocy pomaga w odczytaniu kodu (z g ++ 4.2 STL):

Ćwiczenia:

// from <vector> -> <bits/stl_vector.h> 
template<typename _Tp, typename _Alloc = std::allocator<_Tp> > 
class vector : protected _Vector_base<_Tp, _Alloc> 
{ 
    // Concept requirements. 
    typedef typename _Alloc::value_type _Alloc_value_type; // _Alloc contains value_type internal type 
    __glibcxx_class_requires(_Tp, _SGIAssignableConcept) // _Tp is assignable 
[...] 
public: 
    typedef _Tp value_type;     // from here on _Tp is not mentioned 
    typedef typename _Tp_alloc_type::reference reference; // check + typedef 
[...] 
    iterator begin() { 
    // without typedef: 
    // __gnu_cxx::__normal_iterator<pointer, vector_type> begin() { 
[...] 
    reference operator[](size_type __n) 
    // _Tp& operator[](size_type __n) 
[...] 

// from <memory> 
template <typename _Tp> 
class auto_ptr 
{ 
[...] 
    template <typename _Tp1> 
    auto_ptr(auto_ptr<_Tp1>& __a) throw() 

i funkcje:

template <typename _InputIterator, typename _Tp> 
inline _InputIterator find(_InputIterator __first, _InputIterator __last, _Tp value) { 
    // concept requirements 
    __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) 
    [...] 

Wszystkie ich nazwy są poprzedzone _ i albo litery lub drugiego _, które to nazwy zastrzeżone do implementacji i wolą _Tp od _T, ale na końcu widać, że zawsze gdy typ to generyczny nazywa się _Tp , _Tp1 ..., podczas gdy w przypadku niektórych specyficznych wymagań jest on przypisany, wybiera się bardziej sensowną nazwę.

Istnieje cienka linia między nimi, jak na przykład w std::vector istnieją rzeczywiste wymagania dotyczące typu rodzajowego: _Tp muszą być przypisane, ale pod koniec dnia, to jest głównie typ rodzajowy. Nazywanie go _Assignable byłoby dziwne w niektórych pojemnikach, gdzie istnieje więcej niż jedno wymaganie.

+0

Jak pisałeś '_' lub' __ * 'są zarezerwowane dla implementacji (w pewnych zakresach), więc IMHO lepiej jest trzymać się z daleka od używania dowolnego tak nazwanego identyfikatora (nawet jeśli prawdopodobnie nie spowoduje żadnej szkody w ćwiczyć). –

4

Myślę, że to zależy od tego, ile masz parametrów. Jeśli parametr jest typem i jest to jedyny parametr, dlaczego nie może to być po prostu T? Jednak zgadzam się z tobą, że w przypadku wielu parametrów powinny one mieć sensowne nazwy z tego samego powodu, dla którego zmienne powinny zazwyczaj mieć sensowne nazwy.

+2

Dla mnie to zależy bardziej od tego, co reprezentuje każdy argument, niż od tego, czy istnieje więcej niż jeden argument: 'szablon para struct 'jest kompletnym podejściem rozsądnym, podczas gdy' szablon wektor class' is * missing *, że 'U' musi być alokatorem, a nie typem ogólnym. –

1

Z pewnością nazwy ekspresyjne dla typów szablonów są uporządkowane. Byłoby jeszcze bardziej użyteczne, gdy pewnego dnia pojawią się pojęcia w języku (szkoda, że ​​zostały one zrzucone dla C++ 0x). W międzyczasie nazwa typu parametru szablonu określa oczekiwanie dla danego typu, przynajmniej nieformalnie (pojęcia dałyby im formalność, wymieniając oczekiwane typy i operacje, jakie musi posiadać typ).

1

Różne standardy kodowania definiują różne nazwy. Po prostu wybierz jeden i trzymaj się go.

Moje preferencje to posiadanie opisowych nazw, a nie jakiejś nazwy rodzajowej T (chociaż w niektórych sytuacjach nie jest ona zła).

1

Myślę, że głównym problemem z nazwami jednoliterowymi (w szablonach i innych przypadkach) jest sytuacja, w której chcesz wykonać wyszukiwanie i zamień. Jeśli twój edytor tekstu nie zawiera parsera C++ (a większość nie), nazwy jednoliterowe spowodują wiele fałszywych dopasowań, których nie zamierzałeś. Przy dłuższych/opisowych nazwach, OTOH, wyszukiwanie i zamienianie będzie działać lepiej.

1

Jeśli jest to tylko typ, używam jednoliterowych identyfikatorów (T, U itp.). Jeśli argument ma specjalne, bardziej ograniczone znaczenie (predykat, przydział itp.), Użyłbym czegoś bardziej opisowego.

Jednoliterowe identyfikatory (T) mogą jednak odpalać, kolidując z nazwami makr (patrz GCC 4.2 Template strange error), co jest prawdopodobnie mało prawdopodobne w przypadku dłuższych identyfikatorów (jeśli nie używają tej samej konwencji ALL_CAPS jako makr) .

Powiązane problemy