(I'm learning concepts and templates so correct me if I'm very wrong with something.) I have a function that takes a concept as parameter. I'm now trying to overload this function that takes a more specific concept. That would do "something more specific" or call the less specific function.
template<typename T>
concept Concept1 = ...;
template<typename T>
concept MoreSpecificConcept = ...;
Concept1 <T> &&
...;
//...
void someFunc(const Concept1 auto& x)
{
//do general stuff
}
void someFunc(const MoreSpecificConcept auto& x)
{
if(...)
{
//do specific stuff
}
else
{
//do the more general thing:
// Problem. Trying to call itself:
someFunc(x);
}
}
Is there any way to explicitly tell the compiler which overload to call (like someFunc<Concept1>(x)
which doesn't work), or is it solely dependent on the type of the passed object? Lets say that I can't cast x
to the more-general type and that the more general function / concept don't know about this more specific function / concept so they can't exclude it with a constraint.
Edit: the functions are meant to be within the same (global) namespace.
C++ lets you specify more than one function of the same name in the same scope. These functions are called overloaded functions, or overloads. Overloaded functions enable you to supply different semantics for a function, depending on the types and number of its arguments.
There are mainly two types of overloading, i.e. function overloading and operator overloading. Function overloading improves the code readability, thus keeping the same name for the same action. Operator overloading allows redefining the existing functionality of operators, thus by giving special meaning to them.
Method overloading is a salient feature in Object-Oriented Programming (OOP). It lets you declare the same method multiple times with different argument lists.
The usual workaround for that would be a separated helper function:
void somefunc(const Concept1 auto& x) {
// general stuff
}
void somefuncSpecific(const Concept1 auto& x) {
somefunc(x);
}
void someFuncSpecific(const MoreSpecificConcept auto& x)
{
if(...)
{
//do specific stuff
}
else
{
//do the more general thing:
somefunc(x);
}
}
Another workaround without having separated functions is to use if constexpr
:
void someFuncSpecific(const Concept1 auto& x)
{
if constexpr(MoreSpecificConcept<decltype(x)>)
{
if (...)
{
//do specific stuff
// skip the rest:
return;
}
}
//do the more general thing:
somefunc(x);
}
If possible (mostly depends of both concepts), Another work-around is to create wrapper which only satisfies Concept1
but not MoreSpecificConcept
:
template <Concept1 T>
struct AsConcept1
{
T& t;
// operations to satisfy Concept1 (but not MoreSpecificConcept)
// using some_type = typename Concept1::some_type
// void bar() { t.bar(); }
// ...
};
and then you might do
void someFunc(const MoreSpecificConcept auto& x)
{
if (...) {
// do specific stuff
} else {
// do the more general thing:
someFunc(AsConcept1{x});
}
}
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