2013-01-28 11 views
5

mam tej klasy:Zwiększenie czasu kompilacji zmienna z każdej instancji rodzajowe klasy

template <typename T, uint64_t N> 
struct Probe { 
    static const uint64_t Counter = N; 
    typedef T Type; 
}; 

Który ja wykorzystać jako:

typedef Probe <int, 0> FirstIntProbe; 
typedef Probe <int, 1> SecondIntProbe; 
typedef Probe <float, 2> FloatProbe; 

Czy jest możliwe aby utworzyć raz skompilować \ metodę makro co pozwala mi na utworzenie instancji tej klasy bez określenia drugiego parametru, takiego jak:

typedef Probe <int, Something?> FirstIntProbe; 
typedef Probe <int, Something?> SecondIntProbe; 
typedef Probe <float, Something?> FloatProbe; 

Zakładam to nie jest możliwe, ale znowu widziałem, jak ludzie robią różne rzeczy w C++, o których wcześniej nie sądziłem.


Aktualizacja:

  • Nie jest konieczne, aby zwiększyć o jeden, to jest po prostu ważne, że każda sonda posiada swój własny numer.
  • Nie jest konieczne posiadanie niepowtarzalnej liczby w różnych plikach .cpp \ jednostek tłumaczeniowych.
+3

Czy ważne jest, aby wartości N zaczynały się od 0 i zawsze były sekwencyjne? A co z zachowaniem w jednostkach tłumaczeniowych? Niektóre kompilatory mają wartość "__COUNTER__", która może wystarczyć dla twoich celów. –

+0

Zaktualizowano pytanie –

Odpowiedz

7

Możesz zajrzeć na użyciu __COUNTER__ makro, która jest rozszerzeniem kompilatora (ale obsługiwane na GCC i MSVC, między innymi). Zauważ, że __COUNTER__ jest unikalna tylko dla jednostki tłumaczeniowej, tj. Na plik .cpp.

edycja: Włączenie nagłówka w wielu jednostkach tłumaczeniowych jest w porządku. Ten przykład linki i działa perfekcyjnie (zbudowane na GCC 4.5):

probe.h:

template <typename T, int N> 
struct Probe { 
    typedef T Type; 
}; 

#define DECLARE_PROBE(type) typedef struct Probe<type, __COUNTER__> 

main.cpp:

#include "test.h" 

DECLARE_PROBE(int) intprobe; 
DECLARE_PROBE(float) floatprobe; 

int main(int argc, char** argv) { 
    intprobe ip; 
    floatprobe fp; 
    return 0; 
} 

test.cpp:

#include "test.h" 

DECLARE_PROBE(int) intprobe; 
DECLARE_PROBE(float) floatprobe; 

static intprobe ip; 
static floatprobe fp; 
+2

Jak to działa? '__COUNTER__' jest rozszerzany dla każdego użycia w każdej jednostce tłumaczeniowej. Więc jeśli 'Probe' znajduje się w nagłówku i znajduje się w więcej niż jednej jednostce tranlacyjnej, będziesz mieć niezdefiniowane zachowanie, z powodu naruszenia zasady jednej definicji, a nawet jeśli' Probe' występuje tylko w jednej jednostce tłumaczeniowej, jeśli '__COUNTER__' jest częścią makra, zostanie tylko raz rozwinięte. –

+0

Jak już wspomniałem, "__COUNTER__" jest tylko unikalną jednostką tłumaczeniową. '__COUNTER__' rozszerza się poprawnie w przypadku użycia makr; spróbuj '#define DECLARE_PROBE (type) typedef struct Probe ' on for size. – sheu

+0

Edytowałem odpowiedź przy użyciu przykładu. Całkiem dobrze jest dołączyć definicję klasy i makra do wspólnego nagłówka. – sheu

5

Jest to bardzo proste: , jeśli nie potrzebujesz integralnego wyrażenia stałego (tj. nie używasz Counter jako wymiaru tablicy lub podobnego): po prostu użyj globalnej statycznej dla licznika (lub umieść ją w niesformowanej klasie bazowej), a zwiększ ją za każdym razem, gdy użyjesz go w inicjalizacja. Coś jak:

int currentProbeCounter; 

template <typename T> 
struct Probe 
{ 
    static int const counter; 
    // ... 
}; 

template <typename T> 
const int Probe<T>::counter = ++ currentProbeCounter; 

pamiętać, że to tylko przyporządkowania Probe<T>::counter dla go używać dany typ kiedy (lub jeśli); możesz go użyć w konstruktorach Probe (nawet jeśli nie potrzebujesz) do zapewnienia jego utworzenia. (Z drugiej strony, jeśli nigdy go nie używasz, kogo to obchodzi, jeśli nigdy nie zostanie utworzony.)

+1

Używanie rzeczywistej zmiennej statycznej dla licznika wymaga od kompilatora utworzenia pamięci (i inicjalizacji) dla niego; nie może to być lepsze niż użycie stałego parametru szablonu dla licznika, który nie wymaga przechowywania i umożliwia kompilatorowi optymalizację i złożenie go w wyrażenia. – sheu

+0

@sheu Ale nie ma innego rozwiązania (które znam), które działa. Wszystko za pomocą makr nie powiedzie się, gdy tylko użyjesz wielu jednostek tłumaczeniowych. –

+0

Z wyjątkiem powyższego makra? – sheu

Powiązane problemy