What is the equivalent of cast for concepts?

657 views Asked by At

Consider a class A satisfies two concepts ConceptA and ConceptB. Let a function foo is overloaded for the two concepts:

void foo(ConceptA& arg);
void foo(ConceptB& arg);
A a;
fun(concept_cast<ConceptA>(a));

Note: This example uses the "Terse Notation" syntax proposed as part of N3701, ยง5

Is there something exist like concept_cast which allows users to select the overload?

Eg: Lets say ConceptA says T has to have a member function bar() ConceptB says T has to have a member function baz() and class A has both bar() and baz() member function

Its clearly ambiguous, but is there a way to explicitly select like we have static_cast for normal overloads?

Update: Accepted answer is more than 2 years old. Any update in c++17?

2

There are 2 answers

0
je4d On BEST ANSWER

If one of the concepts is a more constrained version of the other, (e.g. everything that satisfies ConceptA will also satisfy ConceptB but not vice versa), then the most-constrained overload that A satisfies will be chosen.

If neither concept is more constrained than the other, then the two are considered to be ambiguous overloads. Given how you phrased the question, I expect you already knew this.

Regarding concept_cast, I don't think there's anything like that in the current proposal. At least not as of the Bristol meeting (Apr '13). I don't expect this to have changed as the current focus seems to be on making sure the core of the concepts-lite/constraints proposal is workable and acceptable to the committee.

There'll probably be some demand for explicitly picking overloaded template functions like that, and maybe such a cast is the right thing, but I'm not so sure. Consider that such a cast would only be useful for overload disambiguation, where as static_cast is a more general feature. The result of the concept_cast would be same as the original value outside the context of overload resolution!

Edit: Looking at the latest proposal (N3701), there's no provision for explicitly specifying which template function to instantiate.

1
Luc Danton On

Your claim that static_cast can be used to explicitly select a 'normal' overload is specious. It is possible to write the following in today's C++:

template<typename P, EnableIf<NullablePointer<P>>...>
void foo(P&);

template<typename It, EnableIf<Iterator<It>>...>
void foo(It&);

Assuming that NullablePointer and Iterator perform concept checking for the associated Standard concepts, then int* q; foo(q); has no hope of compiling because int* is both a model of NullablePointer and of Iterator (and neither concept subsumes the other). There's nothing obvious to static_cast to to help with that situation.

My example (that you can test for yourself) is extremely relevant because this kind of code is what Concepts Lite attempts to formalize. The overload set you're presenting is equivalent to:

template<typename A>
    requires ConceptA<A>
void foo(A& arg);

template<typename B>
    requires ConceptB<B>
void foo(B& arg);

Notice the similarity between the requires clauses and the EnableIf 'clauses'.