dimanche 29 mai 2016

unordered_map emplacement fails when switching from GCC 4.9.3 to 5.3.1 (with CUDA)

I'm using the following code (irrelevant parts removed)

template<typename Key, typename T, typename... Args>
class Foo {
    // ... etc. ...

    using grault = T* (*)(Args...);
    std::unordered_map<Key,grault> bar;

    template<typename U> static T* quux(Args... args)
    {
        return new U(std::forward<Args>(args)...);
    }

    template<typename U> baz(const Key& key) {
        emplace(key, &quux<U>);
    }
    // ... etc. ...
}

And my template arguments are: Key=std::__cxx11::string, T=ClassA, Args=<const corge &>, U=SomeSubclassOfA (you only care about they Key, really).

Now, that builds and runs fine with GCC 4.9.3 + CUDA 7.5, but fails with GCC 5.3.1 and CUDA 8.0 RC. The error message is:

/usr/include/c++/5/bits/hashtable.h(1526): error: no instance of overloaded function "std::forward" matches the argument list
            argument types are: (const std::__cxx11::string)
          detected during:
            instantiation of "std::pair<std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::iterator, __nv_bool> std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_M_emplace(std::true_type, _Args &&) [with _Key=std::__cxx11::string, _Value= etc. etc. ... (726): here

Now, I'm guessing this is either due to the GCC version switch, or the CUDA version switch, probably the former. I vaguely remember something about an ABI change w.r.t. strings which can get you into trouble, but don't know if this has anything to do with that.

Notes:

  • Yes, this is part of a factory implementation, but the question is not about that.
  • A (possibly) similar issue was reported for Intel ICC http://ift.tt/1OW6pDF

Aucun commentaire:

Enregistrer un commentaire