burbokop
burbokop

Reputation: 11

Template-template function overloading ambiguity error using gcc

I have this code perfectly working on clang

template <template <typename, typename> typename T>
struct CollectIntoAllocatedContainer
{
    // ...
};

template <template <typename, typename, typename> typename T>
struct CollectIntoAllocatedContainerWithCharTraits
{
    // ...
};

template <template <typename, typename> typename T>
constexpr CollectIntoAllocatedContainer<T> collect()
{
    return {};
}

template <template <typename, typename, typename> typename T>
constexpr CollectIntoAllocatedContainerWithCharTraits<T> collect()
{
    return {};
}

int main() {
    collect<std::vector>().dosomething();
    collect<std::basic_string>().dosomething();
}

But it fails on gcc with error:

error: call of overloaded ‘collect<template<class _CharT, class _Traits, class _Alloc> class std::__cxx11::basic_string>()’ is ambiguous
   78 |     collect<std::basic_string>();
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~^~
note: candidate: ‘constexpr CollectIntoAllocatedContainer<T> collect() [with T = std::__cxx11::basic_string]’
   64 | constexpr CollectIntoAllocatedContainer<T> collect()
      |                                            ^~~~~~~
note: candidate: ‘constexpr CollectIntoAllocatedContainerWithCharTraits<T> collect() [with T = std::__cxx11::basic_string]’
   70 | constexpr CollectIntoAllocatedContainerWithCharTraits<T> collect()
      |                                                          ^~~~~~~

I tried concepts:

template <template <typename, typename> typename T, typename V>
concept AllocatedContainer = requires(V x) {
     typename T<V, std::allocator<V>>;
};

template <template <typename, typename, typename> typename T, typename V>
concept AllocatedContainerWithCharTraits = requires(V x) {
     typename T<V, std::char_traits<V>, std::allocator<V>>;
};


template <template <typename, typename> typename T>
constexpr CollectIntoAllocatedContainer<T> collect()
    requires AllocatedContainer<T, std::monostate>
{
    return {};
}

template <template <typename, typename, typename> typename T>
constexpr CollectIntoAllocatedContainerWithCharTraits<T> collect()
    requires AllocatedContainerWithCharTraits<T, std::monostate>
{
    return {};
}

but no result

I use:

Is this a bug of gcc? Or does clang wrongly allow such code? Is there some workaround? Thank you for your help.

P.S: I can not change versions of compilers because they are tied to corporate infrastructure in my company.

Upvotes: 1

Views: 39

Answers (0)

Related Questions