Frage

Nach der Beantwortung diese Frage, die ich is_complete Vorlage in Boost-Bibliothek zu finden versuche, und ich erkannte, dass es keine solche Vorlage in Boost.TypeTraits ist. Warum gibt es keine solche Vorlage in Boost-Bibliothek? Wie sollte es aussehen?

//! Check whether type complete
template<typename T>
struct is_complete
{   
  static const bool value = ( sizeof(T) > 0 );
};

...

// so I could use it in such a way
BOOST_STATIC_ASSERT( boost::is_complete<T>::value );

Der obige Code ist nicht korrekt, weil es illegal ist sizeof auf einen unvollständigen Typen anzuwenden. Was eine gute Lösung sein? Ist es möglich, SFINAE in diesem Fall anzuwenden irgendwie?


Nun, dieses Problem nicht ohne Verletzung der ODR Regel , aber es gibt es eine plattformspezifische Lösung , die für mich funktioniert .

War es hilfreich?

Lösung

Die Antwort von Alexey Malistov gegeben auf MSVC mit einer kleinen Modifikation verwendet werden:

namespace 
{
    template<class T, int discriminator>
    struct is_complete {  
      static T & getT();   
      static char (& pass(T))[2]; 
      static char pass(...);   
      static const bool value = sizeof(pass(getT()))==2;
    };
}
#define IS_COMPLETE(X) is_complete<X,__COUNTER__>::value

Leider ist die COUNTER vordefiniertes Makro ist nicht Teil der Norm, so dass es nicht auf jedem Compiler funktionieren würde.

Andere Tipps

template<class T>
struct is_complete {
    static T & getT();
    static char (& pass(T))[2];
    static char pass(...);

    static const bool value = sizeof(pass(getT()))==2;
};

Es ist vielleicht ein bisschen spät, aber bisher keine C ++ 11-Lösung arbeitete sowohl vollständige als auch abstrakte Typen.

So, hier sind Sie.

Mit VS2015 (v140), g ++> = 4.8.1, Klirren> = 3,4, das funktioniert:

template <class T, class = void>
struct IsComplete : std::false_type
{};

template <class T>
struct IsComplete< T, decltype(void(sizeof(T))) > : std::true_type
{};

Dank Bat-Ulzii Luvsanbat: https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update -1 /

Mit VS2013 (V120):

namespace Details
{

    template <class T>
    struct IsComplete
    {
        typedef char no;
        struct yes { char dummy[2]; };

        template <class U, class = decltype(sizeof(std::declval< U >())) >
        static yes check(U*);

        template <class U>
        static no check(...);

        static const bool value = sizeof(check< T >(nullptr)) == sizeof(yes);
    };

} // namespace Details


template <class T>
struct IsComplete : std::integral_constant< bool, Details::IsComplete< T >::value >
{};

Dies wird von dem internets inspiriert und statische behaupten, Vorlage Typname T ist nicht vollständig?

Ich fürchte, Sie nicht so ein is_complete Typ Merkmale implementieren können. Die Umsetzung gegeben durch @Alexey nicht auf G ++ 4.4.2 und G ++ 4.5.0 kompilieren:

  

Fehler: Initialisieren Argument 1 von 'static char (& is_complete :: Pass (T)) [2] [mit T = Foo]

Auf meinem Mac, mit G ++ 4.0.1 Auswertung is_complete<Foo>::value wo struct Foo; unvollständige Ausbeuten true was noch schlimmer ist als ein Compiler-Fehler ist.

T kann sowohl vollständig und unvollständig im gleichen Programm sein, auf der Übersetzungseinheit abhängig, aber es ist immer die gleiche Art. Als Folge, wie oben ausgeführt, ist is_complete<T> immer auch die gleiche Art.

Wenn Sie also respektieren ODR es nicht möglich ist is_complete<T> müssen unterschiedliche Werte Auswertung je auf denen es verwendet wird; sonst würde es bedeuten, Sie verschiedene Definitionen für is_complete<T> haben, die ODR verbietet.

EDIT: Als akzeptierte Antwort, ich mich um eine Lösung gehackt, die die __COUNTER__ Makro verwendet ein anderes is_complete<T, int> Typ jedes Mal des IS_COMPLETE Makro verwendet wird instanziiert. Doch mit gcc, konnte ich nicht bekommen SFINAE in erster Linie zu arbeiten.

Die Lösung erfordert dies die Berechnung des Standardargument der Merkmalsvorlage durchgeführt wird, als Versuch, die Definition einer Vorlage zu ändern gegen die ODR-Regel (obwohl eine Kombination aus __COUNTER__ und namespace {} kann um ODR arbeiten).

Das in C ++ 11 geschrieben wird, sondern kann angepasst werden, arbeitet in C ++ 03-Modus eines mäßig letzten C ++ 11-kompatible Compiler.

template< typename t >
typename std::enable_if< sizeof (t), std::true_type >::type
is_complete_fn( t * );

std::false_type is_complete_fn( ... );

template< typename t, bool value = decltype( is_complete_fn( (t *) nullptr ) )::value >
struct is_complete : std::integral_constant< bool, value > {};

Online-Demo.

Das Standardargument ausgewertet wird, in dem die Vorlage benannt ist, so kann es zwischen verschiedenen Definitionen kontextuell wechseln. Es besteht keine Notwendigkeit für eine andere Spezialisierung und Definition bei jedem Gebrauch; Sie brauchen nur eine für true und eine für false.

Die Regel ist gegeben in §8.3.6 / 9, die in gleicher Weise auf Funktion Standardargumente und Standard-Template-Argument gilt:

  

Standardargumente ausgewertet werden jedes Mal, wenn die Funktion aufgerufen wird.

Aber Vorsicht, mit diesem in einer Vorlage ist fast sicher, dass die ODR zu verletzen. Eine Vorlage auf einem unvollständigen Typ instanziiert darf nichts anders machen, wenn sie während einer vollständigen instanziiert wurden. Ich persönlich nur das will für ein static_assert.

Im übrigen kann dieses Prinzip auch hilfreich sein, wenn man in die andere Richtung und implementieren die Funktionalität von __COUNTER__ Vorlagen und Überlastung werden.

Just Geläute in zu signalisieren, dass eine Antwort (nicht von mir gegeben) an eine unabhängige Frage eine Lösung für die is_complete<T> Vorlage gibt.

Die Antwort ist hier . Ich bin es nicht unten, um das Einfügen nicht versehentlich Kredit für es.

Ich kann nichts im Standard finden, die sizeof auf einem unvollständigen Typ garantiert, dass 0. ergeben wird Es erfordert jedoch, dass, wenn T zu einem bestimmten Zeitpunkt nicht vollständig ist, aber später in dieser Übersetzungseinheit abgeschlossen, dass alle Referenzen beziehen sich auf T auf die gleiche Art - so wie ich es gelesen habe, auch wenn T unvollständig ist, wo die Vorlage aufgerufen wurde, würde es es vollständig war zu sagen, erforderlich sein, wenn T in dieser Übersetzungseinheit irgendwo abgeschlossen ist

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