C++20 概念/需要 std::map emplace 无法按预期工作

Dan*_*saf 5 c++ c++-concepts c++20

我正在尝试使用 c++20 概念和要求,并尝试创建一个检查调用有效参数的概念std::map emplace
例如,与C++20 概念非常相似,如何定义带参数的函数的存在?但随后使用 std::map 处的 emplace 函数。
然而,这个概念并不像我期望的那样工作:在 a 上map<string, string>它使用 (int, string) 参数成功,请参见示例。这里发生了什么?

#include <iostream>
#include <concepts>
#include <map>


template<typename Tobj, typename TVal1, typename TVal2>
concept Check = requires (Tobj obj, TVal1 val1, TVal2 val2)
{
    obj.emplace(val1,val2);
};

int main(int, char **)
{  
    std::map<std::string, std::string> map;
    std::cout << Check<decltype(map), std::string, std::string>;        // prints 1, as expected.
    std::cout << Check<decltype(map), int, std::string>;                // prints 1 but would expect 0 don't understand?!
    //        map.emplace(1, std::string("Hello"));                         // because this obviously fails to compile
        
}
Run Code Online (Sandbox Code Playgroud)

康桓瑋*_*康桓瑋 8

由于map::emplace()不是受约束的函数,因此obj.emplace(...)- 子句中的表达式 requires始终有效,因为硬错误仅发生在函数体中。

您可能需要另外检查容器的值类型是否可以从参数构造

template<typename Container, typename... Args>
concept container_emplacable = 
  std::ranges::input_range<Container> &&
  std::constructible_from<std::ranges::range_value_t<Container>, Args...> &&
  requires(Container& c, Args&&... args) {
    requires (requires { c.emplace(std::forward<Args>(args)...); } ||         // for map::emplace
              requires { c.emplace(c.end(), std::forward<Args>(args)...); }); // for vector::emplace
  };
Run Code Online (Sandbox Code Playgroud)

演示

让我简单解释一下上面看似疯狂的语法,它可以被拆分为requires { requires (requires A || requires B); }. 嵌套require要求表达式(requires A || requires B)计算为 以true满足概念,而requires Arequires B分别检测A和是否B是有效表达式。