2016-07-27 13 views
2

Checking if a sequence container is contiguous in memory.
C++ templates that accept only certain typesWie zu erkennen, ob ein Container-Sequenz Lagerung haben garantiert

ich ein einfaches send() Verfahren schreibe, die mit C-Stil Zeiger intern arbeitet. Ich möchte, dass es mit allen garantierten Sequenzcontainern arbeiten kann. Meine Motivation ist ein zweifaches:

  • eine flexible Schnittstelle
  • Effizienz - mit std::array Heapzuweisungen vermeidet.

Hier ist, wie weit ich bin:

template <typename Container> 
void poll(Container &out) 
{ 
    static_assert(std::is_base_of< std::array<typename Container::value_type>, Container >::value || 
        std::is_base_of< std::vector<typename Container::value_type>, Container >::value || 
        std::is_base_of< std::string<typename Container::value_type>, Container >::value, 
        "A contiguous memory container is required."); 
} 

Das Problem ist, std::array einen zweiten Parameter erfordert, und das kann nicht zum Zeitpunkt der Kompilierung bekannt sein. Ist dieses Problem lösbar? Möglicherweise durch einen anderen Ansatz?

+0

Oder fügen Sie einfach eine Überladung hinzu. (Aus diesem Grund können Sie Funktionen nicht teilweise spezialisieren) – MSalters

Antwort

7

Der richtige Weg hier ist, eine Merkmalklasse zu verwenden. std::is_base_of ist eine Art von Merkmal. Grundsätzlich: Sie haben eine Template-Struktur, die einen (Template-) Parameter verwendet und ihr Ergebnis über einen verschachtelten Typ/Wert zurückgibt.

In Ihrem Fall so etwas wie dieses

template<typename T> 
struct HasContiguousStorage: public std::false_type{}; 

template<typename T> 
struct HasContiguousStorage<std::vector<T>>: public std::true_type{}; 
// Specialize others 

Wie Sie nicht aus Standardcontainer ableiten sollte, sollte dies ausreichen. Dies kann auch für das Array überprüfen:

template<typename T, size_t N> 
struct HasContiguousStorage<std::array<T,N>>: public std::true_type{}; 

In Ihrer Funktion können Sie dann entweder überlasten (siehe enable_if) oder Zweig darauf (Niederlassung wird zum Zeitpunkt der Kompilierung ausgewertet werden)

+0

Danke. Das habe ich vergessen. – Flamefire

6

Wie wäre es, wenn der Container eine data() Mitgliedsfunktion hat? (das einen Zeiger zurückgibt)

+0

Nah, std :: string gibt 'const char *' zurück. Es scheint, dass meine Vorbedingungen falsch waren. – Vorac