Как я могу проверить, является ли определенная перегрузка функции недействительной?

Я создаю класс стираемого типа TypeErased, используя std::variant, который может быть целым числом, комплексным числом, вектором или ошибкой.

Пока я создавал оператор сложения (который использует std::visit), я столкнулся с проблемой: я не хочу, чтобы определенные типы складывались вместе, и кажется очень непрактичным создавать перегрузки для каждой отдельной нежелательной комбинации.

Например, он должен иметь возможность складывать целое число с комплексным числом, но не вектор и целое число. Для этого я попытался использовать SFINAE (я думаю) для создания структуры, которая может определить, существует ли перегрузка функции:

#include<iostream>
#include<string>

void print(int) {}

template<auto FuncPtr, typename ...Args>
struct FuncExists
{
  template<typename = decltype(FuncPtr(std::declval<Args>()...))>
  constexpr static std::true_type test(int);
  constexpr static std::false_type test(...);

  constexpr static bool value = decltype(test(0))::value;
};

int main()
{
  std::cout<<"print string exists: "<<FuncExists<print, std::string>().value;
}

Я ожидал, что он сможет определить, действителен он или нет, но всякий раз, когда я пытаюсь проверить его на чем-то, что не должно работать, компилятор выдает ошибку. Когда я пытаюсь пройти std::string:

error: cannot convert 'std::__cxx11::basic_string<char>' to 'int' in argument passing
12 |   constexpr static auto test(int) -> decltype(FuncPtr(std::declval<Args>()...),        std::true_type());

Почему это не работает и как это изменить, чтобы оно работало?

Для ясности я пытаюсь выяснить, существует ли определенная перегрузка для ЛЮБОЙ функции (например, оператора+, греха и т. д.). Поэтому, если я попытаюсь добавить вариант с целым числом и вариант с вектором, он может вызвать исключение.

Хотите ли вы, чтобы перегрузка не компилировалась, или было бы приемлемо, чтобы она что-то делала (например, не выполняла операции или просто возвращала один аргумент) и просто не использовалась?

John Bayko 15.07.2024 22:54

вы говорите о добавлении, затем показываете код метода print. Вы хотите проверить произвольные функции или просто проверить, действителен ли a + b для определенного типа a и b?

463035818_is_not_an_ai 15.07.2024 22:55

Я уточню это в вопросе

hello there 15.07.2024 23:01

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

hello there 15.07.2024 23:07

Можете ли вы использовать C++20?

Evg 15.07.2024 23:40

К тому времени, когда у вас есть указатель на функцию, разрешение перегрузки (хотя, возможно, и тривиальное) уже произошло. Обычный трюк — использовать лямбды (возможно, с decltype, особенно до C++20), но это сильно отличается от того, что у вас было до сих пор.

Davis Herring 16.07.2024 01:31

(Я могу использовать С++ 20). Понятно, я провел кое-какие исследования по этому поводу, но, тем не менее, я все еще получаю нежелательные сообщения об ошибках компилятора :(

hello there 16.07.2024 07:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
136
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

SFINAE происходит только в «прямом» контексте. Здесь шаблоны фиксируются классом, и это становится серьезной ошибкой.

Поскольку у вас C++20, вы можете использовать requires:

template <typename T>
concept is_printable = requires(T t) { print(t); };

Демо

Код в операции — это проблема xy. Они действительно хотят увидеть, существует ли двоичная функция для двух, возможно, разных типов. Изменить, я думаю, это как унарное (sin(x)), так и двоичное.

AndyG 16.07.2024 14:03

@AndyG: Аналогичный ответ: template <typename T, typename U> concept is_some_func_possible = requires(T t, U u) { some_func(t, u); };.

Jarod42 16.07.2024 14:07

Я пытался показать пример с + (со смешанными типами), но int нельзя добавить к std::complex :-/

Jarod42 16.07.2024 14:09

Учитывая ограничения дизайна OP (вариант фиксированного типа), возможно, имеет смысл записать явные перегрузки посетителей для операций, которые их интересуют.

AndyG 16.07.2024 14:13

А учитывая, что они заинтересованы в этих операциях только для подмножества комбинаций типов, содержащихся в варианте, тип результата их операции должен отличаться от типа результата обернутой операции (для учета несовместимых типов), что приводит например, другой вариант. Если только не захотят кинуть, но у меня такое впечатление, что ОП играет с ФП.

AndyG 16.07.2024 14:16

Вы можете добавить двойной и сложный <дабл>

Caleth 16.07.2024 15:22

Привет, ОП, это означает, что мне придется вручную выполнять все операции (sin cos sqrt plus и т. д.)?

hello there 16.07.2024 16:32

Кроме того, у меня есть вопрос. Нет ли общего способа проверить, существует ли перегрузка функции? По моему мнению, это довольно простая задача для компилятора.

hello there 16.07.2024 16:37

Либо с концепцией/особенностями, либо «встроенными», где вам это нужно.

Jarod42 16.07.2024 16:37

ок, немного разочаровывает, лол, в любом случае спасибо за ответ :D

hello there 16.07.2024 16:38

Вы не можете передать «набор перегрузки», поэтому вам придется использовать МАКРОС для передачи «имени» или обернуть набор перегрузки в функтор (например, лямбда: [](auto...args)->sin(args...){ return sin(args...); }.

Jarod42 16.07.2024 16:40

С requires обнаружение идиомы — это всего лишь одна строка, а не целая структура для копирования и вставки ;-)

Jarod42 16.07.2024 16:42

Спасибо, чувак, теперь мне придется узнать об этих концепциях. Они кажутся крутыми

hello there 16.07.2024 16:46

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