[Templates] Unverständliche Template-Instantiierung



  • Hallo, ich versuche gerade Flusspferd auf Windows zu kompilieren und stoße noch auf Probleme, die ich nicht ganz verstehe.

    Ich habe es auf diese Klasse zurückverfolgt:

    class string_impl {
      JSString *str;
    
    protected:
      JSString *get()       { return str; }
      void set(JSString *s) { str = s; }
    
      string_impl();
      string_impl(JSString *s) : str(s) { }
      string_impl(char const *s);
      string_impl(char const *s, std::size_t n);
      string_impl(js_char16_t const *s, std::size_t n);
      string_impl(value const &v);
    
      friend JSString *get_string(string_impl &s);
      friend string_impl wrap_string(JSString *s);
    
    public:
      void *get_gcptr() {
        return &str;
      }
    };
    
    inline JSString *get_string(string_impl &s) {
      return s.get();
    }
    
    inline string_impl wrap_string(JSString *s) {
      return string_impl(s); // Problemstelle
    }
    

    Hier ist die Fehlermeldung:

    1>d:\mozilla\airhockeyjs\thirdparty\boostinclude\boost\type_traits\is_abstract.hpp(72) : error C2139: "flusspferd::object": Eine nicht definierte Klasse ist nicht als Argument für die systeminterne Typeigenschaft "__is_abstract" des Compilers zulässig.
    1> d:\mozilla\flusspferd\include\flusspferd\spidermonkey\value.hpp(35): Siehe Deklaration von 'flusspferd::object'
    1> d:\mozilla\airhockeyjs\thirdparty\boostinclude\boost\type_traits\is_abstract.hpp(144): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "boost::detail::is_abstract_imp<T>".
    1> with
    1> [
    1> T=flusspferd::object
    1> ]
    1> d:\mozilla\airhockeyjs\thirdparty\boostinclude\boost\type_traits\is_convertible.hpp(357): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "boost::is_abstract<T>".
    1> with
    1> [
    1> T=flusspferd::object
    1> ]
    1> d:\mozilla\airhockeyjs\thirdparty\boostinclude\boost\type_traits\is_convertible.hpp(371): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "boost::detail::is_convertible_impl_dispatch_base<From,To>".
    1> with
    1> [
    1> From=JSString *,
    1> To=flusspferd::object
    1> ]
    1> d:\mozilla\airhockeyjs\thirdparty\boostinclude\boost\type_traits\is_convertible.hpp(418): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "boost::detail::is_convertible_impl_dispatch<From,To>".
    1> with
    1> [
    1> From=JSString *,
    1> To=flusspferd::object
    1> ]
    1> d:\mozilla\flusspferd\include\flusspferd\spidermonkey\string.hpp(71): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "boost::is_convertible<From,To>".
    1> with
    1> [
    1> From=JSString *,
    1> To=flusspferd::object
    1> ]

    Das Grundproblem ist Folgendes: in der Template-Klasse value wird an einer Stelle boost::is_convertible verwendet, welche nur komplette Typen akzeptiert.

    Leider findet unter MSVC die Template-Instantiierung von value statt, bevor die Klasse object, welche innerhalb von is_convertible verwendet wird, definiert wurde. Der Grund dafür befindet sich im oben geposteten Code innerhalb der wrap_string-Methode. Es hat offensichtlich mit dem string_impl-Konstruktor zu tun, welcher eine value-Referenz akzeptiert. Ich versteh allerdings nicht warum, da der Konstruktor gar nicht genutzt wird, da es ja den JSString*-Konstruktor gibt.

    Update:

    Hier mal der value-Konstruktor:

    template<typename OtherType>
      explicit value(
        OtherType const &val,
        typename boost::disable_if<
          typename boost::mpl::or_<
            typename boost::is_integral<OtherType>::type,
            typename boost::is_floating_point<OtherType>::type,
            typename boost::is_convertible<OtherType, object>::type
          >::type
        >::type * = 0)
      {
        typename convert<OtherType>::to_value converter;
        *this = converter.perform(val);
      }
    

    Update-Ende;

    Laut den Entwicklern von Flusspferd kompiliert der Code unter GCC.

    Irgendwelche Ideen?

    Danke für die Hilfe!

    p.s. value.hpp inkludiert den oben geposteten code. object.hpp inkludiert value.hpp

    p.p.s. kann man irgendwie genauer herausfinden aufgrund welcher code-stelle welche template-instantiierung vorgenommen wird?



  • Liegt es möglicher Weise daran, dass, auch wenn

    string_impl(JSString *s);

    der für JSString* speziellste Konstruktor ist, MSVC den value-konstruktor

    string_impl(value const &v);

    prüft, ob der passt und bei dieser Gelegenheit die Template-Klasse value mit JSString* instantiiert, selbst wenn der Konstruktor nicht genutzt wird?


  • Mod

    anchelito schrieb:

    Liegt es möglicher Weise daran, dass, auch wenn

    string_impl(JSString *s);

    der für JSString* speziellste Konstruktor ist, MSVC den value-konstruktor

    string_impl(value const &v);

    prüft, ob der passt und bei dieser Gelegenheit die Template-Klasse value mit JSString* instantiiert, selbst wenn der Konstruktor nicht genutzt wird?

    Das fällt unter 14.7.1/5.

    If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place. [Example:
    template <class T> struct S {
    operator int();
    };
    void f(int);
    void f(S<int>&);
    void f(S<float>);
    void g(S<int>& sr) {
    f(sr); //instantiation of S<int> allowed but not required
    // instantiation of S<float> allowed but not required
    };
    —end example]

    gcc ist hier schlau, msvc weniger.


Log in to reply