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?
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.
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'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With