所有基本比较(<, <=, ==, !=, >=, >)都有一个关联的函数对象(std::less, std::less_equal, std::equal_to, std::not_equal_to, std::greater_equal, std::greater)。
飞船操作员<=>有类似的函数对象吗?如果没有,为什么没有将其添加到标准库中?
现有元组重载std::get仅限于按索引或类型返回 1 个元素。想象一下,有一个包含多个相同类型元素的元组,并且您希望将它们全部提取到一个新元组中。
std::get<T>如何实现像这样返回给std::tuple定类型的所有出现的版本?
template<typename... Ts_out>
constexpr std::tuple<Ts_out...> extract_from_tuple(auto& tuple) {
// fails in case of multiple occurences of a type in tuple
return std::tuple<Ts_out...> {std::get<Ts_out>(tuple)...};
}
auto tuple = std::make_tuple(1, 2, 3, 'a', 'b', 'c', 1.2, 2.3, 4.5f);
auto extract = extract_from_tuple <float, double>(tuple);
// expecting extract == std::tuple<float, double, double>{4.5f, 1.2, 2.3}
Run Code Online (Sandbox Code Playgroud)
不确定按std::make_index_sequence元素访问每个元素是否可行。std::get<index>std::is_same_v
以下代码在nis时无法编译,但在和size_t时运行良好。intunsigned
#include <vector>
#include <ranges>
int main() {
size_t n = 1;
auto view = std::ranges::iota_view{n, n};
std::vector test(view.begin(), view.end()); //std::vector dislikes these iterators
}
Run Code Online (Sandbox Code Playgroud)
传统的std::for_each返回函数作为标准只需要根据[alg.foreach]Function满足Cpp17MoveConstructible:
\n\nRun Code Online (Sandbox Code Playgroud)\ntemplate<class InputIterator, class Function>\n constexpr Function for_each(InputIterator first, InputIterator last, Function f);\n前提条件:
\nFunction满足Cpp17MoveConstructible要求。[注意:\xe2\x80\x82
\nFunction不需要满足Cpp17CopyConstructible的要求。尾注]
这是合理的,因为用户可能希望在调用后重用该函数。
\n的并行版本for_each没有返回:
\n\nRun Code Online (Sandbox Code Playgroud)\ntemplate<class ExecutionPolicy, class ForwardIterator, class Function>\n void for_each(ExecutionPolicy&& exec,\n ForwardIterator first, ForwardIterator last,\n Function f);\n前提条件:
\nFunction满足Cpp17CopyConstructible要求。
这是因为标准要求Function满足Cpp17CopyConstructible,因此不需要返回该函数,因为用户可以根据需要在调用方自由创建副本。
我注意到ranges::for_each …
c ++标准的最后一个草案引入了所谓的"自定义点对象"([customization.point.object]),它们被范围库广泛使用.
我似乎明白,他们提供一种方式来编写的定制版本begin,swap,data等,这是由ADL标准库中找到.那是对的吗?
这与用户begin在她自己的命名空间中为她的类型定义重载的先前实践有何不同?特别是,他们为什么反对?
在C ++ 20中,已经制作了许多(大多数?)C ++标准库算法constexpr。然而- std::accumulate还没有。
这似乎是它可能是:
template<class InputIt, class T>
constexpr T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first;
}
return init;
}
Run Code Online (Sandbox Code Playgroud)
所以-是否也没有理由constexpr吗?
该概念equality_comparable_with<T, U>旨在声明类型T和 的对象U可以相互比较,如果它们是,则这具有预期的含义。没关系。
但是,这个概念也需要common_reference_t<T&, U&>存在。其主要推动力common_reference及其伴随的功能似乎是启用代理迭代器,有一个地方来表示此类迭代器之间的关系reference以及value_type此类迭代器的关系。
太好了,但是……这与测试 aT和 a 是否U可以相等有什么关系?为什么标准要求这样做T并且U有一个共同的参考关系只是为了让你比较它们相等?
这会产生奇怪的情况,其中很难有两种类型没有合理地具有逻辑可比性的公共引用关系。例如,vector<int>和pmr::vector<int>逻辑上应该是可比的。但它们不可能,因为这两种不相关的类型之间没有合理的公共引用。
考虑:
#include <compare>
template<class=void>
constexpr int f() { return 1; }
unsigned int x;
using T = decltype(x <=> f());
Run Code Online (Sandbox Code Playgroud)
GCC 和 MSVC 接受T. Clang 拒绝了它,并显示以下错误消息:
Run Code Online (Sandbox Code Playgroud)<source>:7:26: error: argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int' using T = decltype(x <=> f()); ^ 1 error generated.
(现场演示)
如果模板头 ( template<class=void>) 被移除,或者如果f在 的声明之前显式或隐式实例化T,则 Clang 接受它。例如,Clang 接受:
#include <compare>
template<class=void>
constexpr int f() { return 1; }
unsigned x; …Run Code Online (Sandbox Code Playgroud) 注意:这个问题被简要标记为this的重复,但它不是一个完全重复的,因为我专门询问 std::optionals 。如果您关心一般情况,仍然是一个值得阅读的好问题。
假设我有嵌套的选项,像这样(愚蠢的玩具示例):
struct Person{
const std::string first_name;
const std::optional<std::string> middle_name;
const std::string last_name;
};
struct Form{
std::optional<Person> person;
};
Run Code Online (Sandbox Code Playgroud)
和这个垃圾邮件功能:
void PrintMiddleName(const std::optional<Form> form){
if (form.has_value() && form->person.has_value() && form->person->middle_name.has_value()) {
std::cout << *(*(*form).person).middle_name << std::endl;
} else {
std::cout << "<none>" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
展平此可选检查的最佳方法是什么?我做了这样的东西,它不是可变参数,但我不太关心(membr3如果真的有必要,我可以再添加一个级别(用 重载),除此之外的一切都是糟糕的代码)。
template<typename T, typename M>
auto flatten_opt(const std::optional<T> opt, M membr){
if (opt.has_value() && (opt.value().*membr).has_value()){
return std::optional{*((*opt).*membr)};
}
return decltype(std::optional{*((*opt).*membr)}){};
}
template<typename T, typename M1, typename M2> …Run Code Online (Sandbox Code Playgroud) c++ ×10
c++20 ×10
constexpr ×2
std-ranges ×2
accumulate ×1
c++-chrono ×1
c++-concepts ×1
iterator ×1
stdoptional ×1
tuples ×1