1

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:

  • gcc 13.3.0
  • clang 17.0.2 (android, armv7, ndk: 26.1.10909125)

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.

3
  • Please member to post minimal reproducible example. Your example needs patching to be reproducible: godbolt.org/z/PE7EbWKss Commented Jan 9 at 15:51
  • Problem is caused by default types for template parameters, so std::basic_string can be used with only two explicit template parameters. See demo: godbolt.org/z/na9jnj9bq Commented Jan 9 at 15:55
  • Note also that clang 19 behaves same as gcc (your example compiles on clang 18 but fails on 19). Commented Jan 9 at 16:06

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.