Могут ли концепции C++ работать с перегруженными наборами?

C++ имеет неприятное ограничение, заключающееся в невозможности передачи перегруженных функций в шаблоны, например, std::max нельзя использовать с std::transform.

Я думал, что было бы неплохо, если бы концепции могли решить эту проблему, но в своих попытках я столкнулся с той же проблемой. Похоже, что концепции не могут ограничивать шаблон на основе предиката по типу функции.

Пример :

      #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;
}

заметки:

  • Я знаю о разных решениях этой проблемы, это всего лишь пример проблемы, чтобы конкретно спросить, можно ли это сделать с помощью концепций.
  • Я знаю, что просто диспетчеризация по арности примитивна, например, предикат также должен возвращать , так далее.

1 ответ

Чтобы язык рассмотрел, соответствует ли тип концепции, C++ должен сначала вывести тип аргумента и подключить его к функции шаблона. Такой вывод невозможен, потому что аргумент — это имя, представляющее функцию с несколькими перегрузками. Таким образом, у концепций даже нет шанса сработать.

Пока выражение, состоящее из имени перегруженной функции, не может подвергаться выводу аргумента шаблона, то, что вы пытаетесь сделать, не может работать.

И даже если бы это сработало, это все равно не сработало бы . В этом гипотетическом, fnсоответствует обоим понятиям. И хотя перегрузка на основе концепций — это вещь, она основана на сравнении атомарных ограничений, чтобы найти сходство, чтобы увидеть, что более ограничено. Но их атомарные ограничения не связаны (насколько это касается C++). Таким образом, оба будут считаться в равной степени действительными, и, следовательно, перегрузка концепций не удастся.

Вам просто нужно будет сделать то, что делают все остальные: создать лямбду.

Другие вопросы по тегам