2014-10-20 7 views
5

Say my kod wykorzystuje std :: tablicę, chciałbym zrobić:w C++, jak owinąć domyślnych nagłówków z awaryjna

pliku: tablica

#pragma once 

#ifdef MY_TOOLSET_HAS_STD_ARRAY 
#include <array> //recursive include here? 
#else 
#include <boost/array.hpp> 
namespace std 
{ 
    using boost::array; 
} 
#endif 

taki, że mój projekt może używać std :: array bez dbania o kompilator/platformę. Jednym z problemów (przynajmniej) jest to, że gdy std :: array jest dostępny, to include będzie rekursywny, kiedy to, czego naprawdę chcę (semantycznie) "będzie zawierał nagłówek, który zostałby zawarty, gdyby ten fragment nie istniał".

Wszelkie pomysły, jak to zrobić? Wiem, że ciągnięcie boost :: array do std może być również uważane za złą praktykę, więc interesują mnie również przemyślenia na ten temat.

+0

To jest niezdefiniowane zachowanie. Użyj jednego z pozostałych. –

+0

Dla przypadku 'tablica' Boost.TR1 powinno to zrobić właściwą rzecz. –

+0

Jest to technicznie niezdefiniowane zachowanie polegające na umieszczaniu rzeczy w 'std', nie jest to zła praktyka (ale zanim wywołają się demony nosowe, powinno działać dobrze). Myślę, że najlepiej będzie, jeśli po prostu nazwiesz swój nagłówek czymś innym (lub umieszczasz go w innym katalogu, np. Boost). – Cameron

Odpowiedz

7

Właściwym sposobem na rozwiązanie tego "problemu" jest nie wprowadzanie go w pierwszej kolejności.

Jeśli niektóre środowiska kompilacyjne obsługują język C++ 11, ale inne nie, należy znaleźć wspólny podzbiór obsługiwany we wszystkich środowiskach kompilacji i używać go. W takim przypadku ten typowy podzbiór wydaje się być Boost. Więc powinieneś użyć boost::array.

Należy również wziąć pod uwagę, że jeśli rozwiniesz test & przy użyciu std::array, pozostawisz nieprzetestowany cały dział kodu - ten używający boost::array.

Jestem za leniwe programowanie - ale inteligentne leniwy programowania.Leniwy programowanie nie oznacza hackowego lub niezdarnego programowania, a inteligentne leniwe programowanie nie wywołuje Nieokreślonego Zachowania, ponieważ dodanie boost::array do przestrzeni nazw std. Mówiąc "Nie chcę przechodzić przez cały mój kod i zmienić std::array na boost::array" nie jest dobrym powodem do wprowadzenia hacków i niezdefiniowanych zachowań. Może to być tak proste, jak wywołanie sed, aby dokonać wszystkich tych zmian, a może to zająć tylko 5 minut.

+0

Więc nie zgadzam się ... i to jedna opcja. Ale jest to projekt z wieloma osobami pracującymi nad nim i byłoby miło poradzić sobie z przypadkiem, w którym wszyscy nie wiedzieli "oh, muszę użyć boost :: array" ... ponieważ działa na platformie, którą oni Rozwijam się. – user109078

+2

@ user109078 Niestety jest to problem dla Twoich menedżerów do rozwiązania. –

+0

Deweloperzy nie powinni rozwijać się za pomocą kompilatora, który nie jest używany w produkcie Prod. –

3

Jest to z pewnością jeden z tych przypadków użycia makr:

// in "my_fixed_array.h" 
#ifdef MY_TOOLEST_HAS_STD_ARRAY 
    #include <array> 
    #define FIX_ARRAY std::array 
#else 
    #include <boost/array.hpp> 
    #define FIX_ARRAY boost::array 
#fi 


// anywhere else 
#include "my_fixed_array.h" 
FIX_ARRAY<char, 4> some_chars; 

W ten sposób nie trzeba iść dookoła robią niegrzeczne rzeczy jak oddanie rzeczy do namespace std.

+1

Nie mogę mówić za innych, ale osobiście wolałbym (nielegalnie) rozszerzać 'std' niż używać makr dla nazw typów ... – Cameron

+1

@Cameron Wolę używać makr. Przynajmniej wynikowy kod byłby legalny. –

+3

@Cameron Nie potrzebujesz makr. Użyj 'namespace my {#ifdef MY_TOOLEST_HAS_STD_ARRAY używając array = std :: array; #else using array = boost :: array; #endif} '. – Praetorian

1

W zależności od tego, jak rozsądna jest implementacja kompilatora (a większość z nich jest całkiem dobra pod tym względem), można po prostu polegać na kolejności wyszukiwania ścieżki dostępu. Domyślny system obejmuje przeszukiwanie ścieżek przed określonymi przez użytkownika "dodatkowymi" ścieżkami.

Więc jeśli masz nagłówek nazwany array który jest w niestandardowym zawierać ścieżkę, można założyć, że będzie tylko być zawarte jeśli średnia <array> nagłówek nie jest obecny, ponieważ system będzie ją znaleźć najpierw inaczej. Zauważ, że nie potrzebujesz nawet huka do wykrywania funkcji za pomocą tej techniki.

(nie powiedzieć, że było dość. - to jest trochę nadużycie środowiska kompilacji, aczkolwiek dość bezpieczną)

4

Można użyć pre-C++ 11 „szablon typedef obejście”dla tego, który nie wiąże #defining nazwy typu, ale robi składnię używania typ nieco brzydsze:

#ifdef MY_TOOLSET_HAS_STD_ARRAY 
    #include <array> 
#else 
    #include <boost/array.hpp> 
#endif 

template <typename T, size_t N> 
struct fixed_array 
{ 
    #ifdef MY_TOOLSET_HAS_STD_ARRAY 
     typedef std::array<T, N> type; 
    #else 
     typedef boost::array<T, N> type; 
    #endif 
}; 

Wtedy twój wykorzystanie rodzaju postać:

typename fixed_array<char, 4>::type some_chars; 

Jednakowoż r, byłoby znacznie prostsze po prostu użyć boost::array. Oznacza to mniej permutacji, które musisz przetestować, a tym samym obniża koszty utrzymania w bazie kodu.

Powiązane problemy