Home > Blockchain >  Can C concepts operate on overload sets?
Can C concepts operate on overload sets?

Time:12-08

C has an obnoxious limitation that it is impossible to pass overloaded functions to templates, for example std::max can not be nicely used with std::transform.

I was thinking that it would be nice if concepts could solve this, but in my attempts I hit the same issue. It looks like concepts are not able to constrain the template based on predicate on function type.

Example:

#include <type_traits>
#include <iostream>
#include <boost/callable_traits/args.hpp>
namespace ct = boost::callable_traits;

template <typename Fn>
concept Fn1 =  std::tuple_size<ct::args_t<Fn>>::value == 1;

template <typename Fn>
concept Fn2 =  std::tuple_size<ct::args_t<Fn>>::value == 2;

template<Fn1 Fn>
auto make(Fn f){
    return 1;
}

template<Fn2  Fn>
auto make(Fn f){
    return 2;
}

auto fn(int a){
}

auto fn(int a, float b){
    return 2;
}

int main() {
    std::cout << make(fn) << std::endl;
    std::cout << make(fn) << std::endl;
}

notes:

  • I know about different solutions to this problem, this is just an example problem to ask specifically if this can be done with concepts.
  • I know that just dispatching on arity is primitive, e.g. predicate should also return bool, etc.

CodePudding user response:

In order for the language to consider whether a type fulfills a concept, C must first deduce the type of the argument and plug it into the template function. That deduction cannot happen because the argument is a name representing a function with multiple overloads. So concepts don't even get a chance to work.

So long as an expression consisting of the name of an overloaded function cannot undergo template argument deduction, what you're trying to do cannot work.

And even if it did work, it still wouldn't work. In this hypothetical, fn fulfills both concepts. And while overloading based on concepts is a thing, it's a thing based on comparing the atomic constraints to look for similarities to see which is more constrained. But their atomic constraints are unrelated (as far as C is concerned). Thus, both would be considered equally as valid, and therefore concept overloading would fail.

You're just going to have to do what everyone else does: create a lambda.

  • Related