Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading functions with concepts

(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.

like image 999
Newline Avatar asked May 27 '21 15:05

Newline


People also ask

What is a function overloading in C++?

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.

What is overloading and its types?

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.

What is overloading in oops concept?

Method overloading is a salient feature in Object-Oriented Programming (OOP). It lets you declare the same method multiple times with different argument lists.


2 Answers

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);
}
like image 83
Guillaume Racicot Avatar answered Nov 15 '22 07:11

Guillaume Racicot


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});
    }
}
like image 27
Jarod42 Avatar answered Nov 15 '22 07:11

Jarod42