Frage

Wie benötige ich und prüfen, ob ein Argument ein gewisses Konzept in C++?

Zum Beispiel erfordert die random_shuffle Funktion im algorithm Header, dass seine Argumente RandomAccessIterators

  template<typename _RandomAccessIterator>
    inline void
    random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
    {
      // concept requirements
      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
            _RandomAccessIterator>)
      __glibcxx_requires_valid_range(__first, __last);

      if (__first != __last)
        for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
          std::iter_swap(__i, __first + (std::rand() % ((__i - __first) + 1)));
    }

Ich glaube, ich nicht diese __glibcxx_function_requires usw. in meinem eigenen Code verwenden kann? Wie arbeiten Sie? Kontrollieren Sie, Dinge wie, dass in Ihrem Code?

War es hilfreich?

Lösung

-Boost hat eine Bibliothek für diese. Es ist wahrscheinlich einfacher und gut dokumentiert als herauszufinden, wie die Version verwenden, um Ihre STL Implementierer zusammen gehackt hat.

http://www.boost.org/doc /libs/1_40_0/libs/concept_check/concept_check.htm

Andere Tipps

Diese Makros definiert weg, es sei denn Sie _GLIBCXX_CONCEPT_CHECKS definieren. Also habe ich versucht, diese in beiden Richtungen zu kompilieren:

#include <list>
#include <algorithm>

int main()
{
    std::list<int> li;
    std::random_shuffle(li.begin(), li.end());
}

Ohne Konzept überprüft: 8 Zeilen Fehler - die Instanziierung, wo kein Spiel für Betreiber. Alles ist klar.

Mit Konzept überprüft: die gleichen Fehler + 50 Zeilen oder so von „instanziiert von hier“ Kauderwelsch mit der Endung „Fehler: Konvertierung von‚std :: bidirectional_iterator_tag‘zu nicht-skalare Typ‚std :: random_access_iterator_tag‘angefordert“. Doh! Ich hätte, dass aus schneller dachte, wenn es einen Kommentar mit dem random_shuffle Algorithmus war.

Eine Sache ist, dass Sie nicht unbedingt diese Kontrollen müssen. Der Code wird nicht kompiliert, wenn die Voraussetzungen nicht erfüllt sind. Und es scheint mir, dass ein einfacher „kein passender Operator <“ klarer als 50 Zeilen Kauderwelsch sein könnte Abschluss (in obskurer Wortlaut), dass „Funktion erfordert weniger als vergleichbares Konzept“.

Wenn Sie diese Kontrollen (für Dinge wie random_shuffle) wollen, ist eine Möglichkeit, den Anruf an eine andere Funktion zu übermitteln, die auch das Recht Iterator-Tag akzeptiert:

#include <list>
#include <algorithm>
#include <iterator>
namespace detail {
template <class Iter>
void shuffle(Iter first, Iter last, std::random_access_iterator_tag)
{
    if (first != last)
        for (Iter i = first + 1; i != last; ++i)
            std::iter_swap(i, first + (std::rand() % ((i - first) + 1)));
}
}

template <class Iter>
void shuffle(Iter first, Iter last)
{
    detail::shuffle(first, last, typename std::iterator_traits<Iter>::iterator_category());
}

int main()
{
    std::list<int> li;
    shuffle(li.begin(), li.end());
}

erzeugt eine nette Nachricht: "keine passende Funktion für Aufruf von 'shuffle (std :: _ List_iterator & std :: _ List_iterator & std :: bidirectional_iterator_tag)'"

Und wenn Sie über-schön sein wollen, können Sie eine Templat-Überlastung hinzufügen, die zum Zeitpunkt der Kompilierung behauptet (static_assert kommt mit C ++ 0x):

template <class Iter, class Tag>
void shuffle(Iter, Iter, Tag )
{
    //test some template-dependent expression that is always false
    //to avoid it from firing unless the function is instantiated
    static_assert(sizeof(Tag) == 0, "shuffle requires random access iterators");
} 

sagt nicht, dass Konzept Checks Auftrieb hat nicht ihren Platz.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top