Я думаю, это была бы очень плохая идея.
visit
сейчас концептуально простая функция. Это делает это:
template <typename F, typename... Variants>
decltype(auto) visit(F f, Variants... vs) {
return f(std::get<vs.index()>(vs)...);
}
За исключением, конечно, vs.index()
не является константным выражением, поэтому вы не можете просто сделать это, вам нужна вся эта сложная реализация, чтобы это работало. Но дело в том, что * visit
группа вариантов просто вызывает f
на текущих альтернативах каждого из них. Это просто, чтобы рассуждать о.
Наличие общего алгоритма для семантически разных вещей, основанных на типах, которые он передает, очень плохая идея. Это означает, что вы не можете на самом деле рассуждать о правильности своего кода - потому что он может делать что угодно Последний пример в OP является хорошим примером этого:
std::visit([](auto&){}, v1, v2); // #1
std::visit([](auto&, auto&){}, v1, v2); // #2
Сегодня #1
(пример OP) не компилируется, потому что вы передаете унарную функцию двоичному посетителю. Это хорошая вещь. Но с предложением, оба скомпилируют и делают дико разные вещи. Один посетил бы каждый вариант последовательно, другой посетил бы каждый вариант вместе.
Каковы были намерения пользователя? Может быть, #1
было ошибкой, и пользователь либо забыл аргумент, либо предоставил посетителя, который работал в качестве бинарного посетителя в большинстве, но не во всех случаях, но работает как унарный посетитель во всех случаях?
<ч />
Другой пример в OP менее плох, который имеет:
visit(f1, f2, f3, v1, v2, v3)
означает троичное посещение по трем комбинированным функциям, а не квазинарное посещение по одной функции:
visit(overload(f1, f2, f3), v1, v2, v3)
Но это было бы очень сложно реализовать, с минимальным усилением (пользователь мог бы просто обернуть функции на своей стороне, верно?), И вы должны начать задавать вопросы типа: что, если у вас есть вызываемый variant
?
Если вы собираетесь использовать другой синтаксис, я видел несколько примеров кода, где люди осуществляют посещение синтаксически следующим образом:
visit2(v1, v2, v3)(f1, f2, f3)
Это очень просто реализовать:
template <typename... Variants>
auto visit2(Variants&&... variants) {
return [&](auto&&... fs) -> decltype(auto) {
return std::visit(overload(FWD(fs)...), FWD(variants)...);
};
}
И имеет преимущество в том, что сначала ставится вариант (ы) и не нужно писать overload
. Может быть, этого достаточно.