C++ 如果在std::visit中,为什么std::重载而不是concepts/constexpr?

C++ 如果在std::visit中,为什么std::重载而不是concepts/constexpr?,c++,variant,c++-concepts,c++20,C++,Variant,C++ Concepts,C++20,我可能对std::重载提案和/或概念有点困惑,但根据我目前对两者的理解,我有以下问题: 为什么C++20不只是概念化/if consteprify std::visit,这样它就可以根据传递给它的参数类型知道该做什么 例如,为什么我们不能让std::visit根据传递的参数的概念修改它的行为(它所需要的只是函数在前面,变量在后面) 例如,这两个visits都接受3个参数,但逻辑不同 std::variant<int, double> v1=4.7; std::vari

我可能对std::重载提案和/或概念有点困惑,但根据我目前对两者的理解,我有以下问题:

为什么C++20不只是概念化/if consteprify std::visit,这样它就可以根据传递给它的参数类型知道该做什么

例如,为什么我们不能让std::visit根据传递的参数的概念修改它的行为(它所需要的只是函数在前面,变量在后面)

例如,这两个
visit
s都接受3个参数,但逻辑不同

    std::variant<int, double> v1=4.7;
    std::variant<bool, std::string> v2=false;
    // calls lambda that is a better fit(double one)
    std::visit([](int& a){std::cout<< sizeof (a);},[](double& a){std::cout << a;} , v1); 
    // calls lambda on variant v1 and then variant v2
    std::visit([](auto& a){}, v1, v2); 
std::variant v1=4.7;
标准::变量v2=假;
//调用更适合的lambda(双1)

我认为这是一个非常糟糕的主意

立即访问
在概念上是一个简单的功能。它可以实现以下功能:

template <typename F, typename... Variants>
decltype(auto) visit(F f, Variants... vs) {
    return f(std::get<vs.index()>(vs)...);
}
今天,
#1
(OP示例)没有编译,因为您正在将一元函数传递给二进制访问者。这是一件好事。但是根据建议,两者都将编译并执行完全不同的操作。一个将按顺序访问每个变体,另一个将同时访问每个变体

用户的意图是什么?可能
#1
是一个bug,用户要么忘记了一个参数,要么提供了一个访问者,在大多数情况下(但不是所有情况下)作为二进制访问者工作,但在所有情况下都作为一元访问者工作


OP中的另一个例子不那么糟糕,它有:

visit(f1, f2, f3, v1, v2, v3)
指三个组合功能的三元访问,而不是一个功能的五元访问:

visit(overload(f1, f2, f3), v1, v2, v3)
但这将是非常复杂的实现,收益最小(用户可以将函数包装在其右侧?),并且您必须开始问这样的问题:如果您有一个可开票的
变体

如果要使用不同的语法,我已经看到了几个代码示例,其中人们在语法上实现了如下访问:

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)...);
    };
}
模板
自动访问2(变体和…变体){
return[&](自动&&…fs)->decltype(自动){
返回标准::访问(过载(FWD(fs)…)、FWD(变体)…);
};
}

它的好处是将变量放在第一位,而不必编写
重载
。也许这已经足够好了。

这将使实现更加复杂(而且已经非常复杂)。我认为它的好处与增加的复杂性不符。CPPNearner说了什么。还有,
std::visit([](auto&a){}
compile似乎很糟糕。(这里可能有一些混淆-注意它没有编译)@Barry为什么cppreference会有变体…作为std::visit签名中的模板类型?重新措辞:如何使其编译…啊,nvm,访问者应该接受2个参数…我错了。但编辑QQ,尽管如此,visit仍然可以推导出访问者的数量,并将其与变体进行匹配向上投票,请为未来读者提供FWD宏的定义
template <typename... Variants>
auto visit2(Variants&&... variants) {
    return [&](auto&&... fs) -> decltype(auto) {
        return std::visit(overload(FWD(fs)...), FWD(variants)...);
    };
}