Alexander Stippler
Alexander Stippler

Reputation: 73

Concept does not resolve ambiguity as expected. What's wrong with the code sample?

I experiment with c++ concepts. Tried to disambiguate a template 'using' clause by using a concept. Here is a simplified sample:

namespace A {

template <typename T>
class Array
{
    public:
        typedef double ElementType;

        Array() {}

        ElementType *data() { return nullptr; }
};

template <typename E>
concept bool Engine =
requires(E e) { {e.data()} -> typename E::ElementType *; };

template <typename E>
requires Engine<E>
class Container
{
    public:
        Container() {};
};

} // namespace A

namespace B {

template <typename T>
using Container = A::Container<A::Array<T>>;

} // namespace B

int main()
{
    using namespace A;
    using namespace B;

    Container<double> d;
    return 0;
}

This yields the following error:

cio.cc: In function 'int main()':
cio.cc:40:3: error: reference to 'Container' is ambiguous
   Container<double> d;
   ^~~~~~~~~
cio.cc:20:7: note: candidates are: 'template<class E>  requires      Engine<E> class A::Container'
 class Container
   ^~~~~~~~~
cio.cc:31:44: note:                 'template<class T> using Container = A::Container<A::Array<T> >'
 using Container = A::Container<A::Array<T>>;
                                        ^
cio.cc:40:13: error: expected primary-expression before 'double'
   Container<double> d;

So why is A::Container considered a candidate for Container? double does not fulfil the concepts. Where am I wrong?

Upvotes: 0

Views: 248

Answers (1)

Barry
Barry

Reputation: 302932

C++20 Concepts just doesn't support that use-case. We have overload resolution for functions, but we don't have overload resolution for types or aliases like this.

Container<dobule> has to refer to one thing, but it could be either A::Container or B::Container... so that's ill-formed. There's no "check if this particular class template satisfies the constraints" step here.

Upvotes: 4

Related Questions