2016-07-29 35 views
0

Kann jemand bitte, erklären 1), warum der folgende Code nicht auf Clang funktioniert und 2) wie sollte es neu geschrieben werden, kompatibel sein mit Clang ?Dynamische Verknüpfung nicht auf Clang für constexpr statisches Element von voll spezialisierten Vorlage

using LinkWeight = float; 

template <bool WEIGHTED=true> 
struct InpLink { 
    using Weight = LinkWeight; //!< \copydoc LinkWeight 
    Weight weight; //!< Link weight 
    // ... 
}; 

template <> 
struct InpLink<false> { 
    using Weight = LinkWeight; //!< \copydoc LinkWeight 
    constexpr static Weight weight = 1; 
}; 

Dieser Code funktioniert auf GCC in Ordnung, hat aber den Verknüpfungsfehler auf Clang 3.8.1 auf Linux Ubuntu x64:

undefined reference to `InpLink :: weight‘

nach der Definition:

template <> 
constexpr typename InpLink<false>::Weight InpLink<false>::weight; 

die Fehler bei der Kompilierung ist: extraneous 'template<>' in declaration of variable 'weight'

Nach der Definition:

template <bool WEIGHTED> 
constexpr typename InpLink<false>::Weight InpLink<false>::weight; 

die Kompilierung Fehler ist:

..cluster.hpp:31:60: error: redefinition of 'weight' as different kind of symbol 
constexpr typename InpLink<false>::Weight InpLink<false>::weight; 
                 ^
..cluster.h:58:27: note: previous definition is here 
     constexpr static Weight weight = 1; 

, die wie ein Klirren Bug sieht ...

HINWEIS: Das gleiche Beispiel funktioniert gut auf CLang, wenn ich 2 Parameter in der Vorlage habe, partielle Spezialisierung durchführen und das statische consExpr-Gewicht wie folgt definieren:

template <bool TMP> 
constexpr typename InpLink<false, TMP>::Weight InpLink<false, UNSIGNED>::weight; 

Mit

template <bool WEIGHTED=true, bool TMP=true> 
struct InpLink { 
    using Weight = LinkWeight; //!< \copydoc LinkWeight 
    Weight weight; //!< Link weight 
    // ... 
}; 

template <bool TMP> 
struct InpLink<false, TMP> { 
    using Weight = LinkWeight; //!< \copydoc LinkWeight 
    constexpr static Weight weight = 1; 
}; 

Offensichtlich Ich möchte keine zusätzlichen Template-Parameter verwenden, um die Verknüpfung Fehler zu überwinden. Gibt es einen anderen Weg, dies zu lösen?
Was ist los mit CLang 3.8.1 oder mit meiner vollständigen Template-Spezialisierung?

Antwort

0

Es scheint also, dass dies ein Fehler in CLang < = 3.8.1 ist, der die Verwendung von consExpr für statische Member in dynamischen Bibliotheken begrenzt und die separate Definition von statischen Membern der vollständig spezialisierten Vorlagen verhindert.
Und der Weg, um es zu überwinden, ist:
1. Verwenden Sie statische Const anstelle von Constexpr für CLang.
2. Definieren Sie statisches Element NUR an die Template-Deklaration entspricht, anstelle der vollständigen Spezialisierung:

template <bool WEIGHTED=false> 
struct InpLink { 
    using Weight = LinkWeight; //!< \copydoc LinkWeight 

    //! Link is unweighted 
    constexpr static bool IS_WEIGHTED = false; 
    //! \copydoc SimpleLink<Weight>::weight 
    // ATTENTION: such complicated definition is required to overcome 
    // the linking error on CLang 
#ifdef __clang__ 
    const 
#else 
    constexpr 
#endif // __clang__ 
    static Weight weight 
#ifndef __clang__ 
     = 1 
#endif // !__clang__ 
    ; 
    // ... 
}; 

template <> 
struct InpLink<true> { 
    using Weight = LinkWeight; //!< \copydoc LinkWeight 
    Weight weight; //!< Link weight 
    // ... 
}; 

Und das statische Gewicht in CPP definieren nicht die Header wie:

#ifdef __clang__ 
// Note: Required by CLang for the linking 
template <> 
const InpLink<false>::Weight InpLink<false>::weight = 1; 
#endif // __clang__ 

PS GCC ist wirklich ein weitaus besserer und viel zuverlässigerer Compiler als CLang für Release-Builds (CLang hat immer noch einige einzigartige Vorteile für das Debuggen).