已批准用于C ++ 20的P0780 (“允许在lambda init-capture中扩展包”)允许通过...在包扩展之前放置省略号()来生成闭合数据包,作为lambda捕获的一部分。
这很有用-例如-在通过移动捕获包时:
template <typename... Ts>
void foo(Ts... xs)
{
bar([...xs = std::move(xs)]{ /* ... */ });
}
Run Code Online (Sandbox Code Playgroud)
在试用此功能时,我想到了这个神秘的构造:
template <typename... Ts>
void foo(Ts... xs)
{
[...xs...]{}();
}
int main()
{
foo(0, 1, 2);
}
Run Code Online (Sandbox Code Playgroud)
g ++(trunk)对其进行编译,但是老实说,我一直在努力理解其含义。这是什么意思?生成闭包作为数据成员将具有什么?
using namespace std;
Run Code Online (Sandbox Code Playgroud)
考虑实体/对象管理的传统OOP方法:
struct Entity { bool alive{true}; }
struct Manager {
vector<unique_ptr<Entity>> entities; // Non cache-friendly
void update() {
// erase-remove_if idiom: remove all !alive entities
entities.erase(remove_if(begin(entities), end(entities),
[](const unique_ptr<Entity>& e){ return !e->alive; }));
}
};
struct UserObject {
// Even if Manager::entities contents are re-ordered
// this reference is still valid (if the entity was not deleted)
Entity& entity;
};
Run Code Online (Sandbox Code Playgroud)
但是,我想尝试一种面向数据的方法:不动态分配Entity实例,而是将它们存储在缓存友好的线性内存中.
struct Manager {
vector<Entity> entities; // Cache-friendly
void …Run Code Online (Sandbox Code Playgroud) template<class> struct Printer;
// I want this to match std::vector (and similar linear containers)
template<template<class, class...> class T, class TV, class... TS>
struct Printer<T<TV, TS...>> { ... };
// I want this to match std::map (and similar map-like containers)
template<template<class, class, class...> class TM, class TK, class TV, typename... TS>
struct Printer<TM<TK, TV, TS...>> { ... }
int main()
{
// Both of these match the second specialization, which is only intended
// for std::map (and similar map-like containers)
Printer<std::vector<int>>::something(); …Run Code Online (Sandbox Code Playgroud) 请考虑以下代码:
template <typename T>
struct dependent_type
{
using type = T;
};
template <typename T>
auto foo(T) -> std::enable_if_t<std::is_same<T, int>{}>
{
std::cout << "a\n";
}
template<typename T>
void foo(typename dependent_type<T>::type)
{
std::cout << "b\n";
}
Run Code Online (Sandbox Code Playgroud)
第一个重载foo可以T从其调用中推断出来.
的第二过载foo是一个非推测的上下文.
int main()
{
foo<int>( 1 ); // prints "b"
foo<double>( 1.0 ); // prints "b"
foo( 1 ); // prints "a"
}
Run Code Online (Sandbox Code Playgroud)
为什么foo<int>( 1 )打印"b"而不是"a"?
看看这个简单的片段:
enum class Enum1 { Value };
enum class Enum2 { Value };
template <auto> struct Foo;
template <> struct Foo<Enum1::Value> { };
template <> struct Foo<Enum2::Value> { };
Run Code Online (Sandbox Code Playgroud)
Clang编译了这个,但是gcc-7.2失败了:
x.cpp:5:20:错误:重新定义'struct Foo <(Enum1)0>'template <> struct Foo {};
此错误消息似乎无效,如第5行所示Enum2::Value.
哪个编译器正确?这是符合规范的代码吗?
我创建了一个小宏元编程库,实现基本的构建体,例如REPEAT(times, x),IF(value, true, false)元组,等等.
我的大多数实现都是通过基于可变参数计数或通过计数器重载宏来实现的:
// Example:
#define REPEAT_0(x)
#define REPEAT_1(x) x REPEAT_0(x)
#define REPEAT_2(x) x REPEAT_1(x)
#define REPEAT_3(x) x REPEAT_2(x)
// ...
// (these defines are generated using an external script)
// ...
#define REPEAT(count, x) CAT(REPEAT_, count)(x)
Run Code Online (Sandbox Code Playgroud)
这很好,但我最近遇到了Paul Fultz的一个非常有趣的宏递归实现.
直到延迟表达部分,我没有理解他的文章.
但是,我在理解使用DEFER和OBSTRUCT正确使用方面遇到了很多麻烦.
Paul实现了一个非常优雅的版本,REPEAT不需要脚本生成的定义,如下所示:
#define EAT(...)
#define EXPAND(...) __VA_ARGS__
#define WHEN(c) IF(c)(EXPAND, EAT)
#define REPEAT(count, macro, ...) \
WHEN(count) \
( \ …Run Code Online (Sandbox Code Playgroud) C++ 17标准说:
有条件地支持
offsetof使用非标准布局类的宏.
有条件地支持
程序构造不需要实现支持
我觉得这个定义offsetof不太精确.
这是否意味着我可以安全地尝试在非标准布局类中使用它?
"条件支持"与实现定义有何不同?
编译器是否不支持offsetof生成诊断所需的特定类型的类?
码:
#include <memory>
struct Data;
std::unique_ptr<Data> make_me();
int main()
{
std::unique_ptr<Data> m = make_me();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然失败了:
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0/memory:80:
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/unique_ptr.h:76:16: error: invalid application of 'sizeof' to an incomplete type 'Data'
static_assert(sizeof(_Tp)>0,
^~~~~~~~~~~
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/unique_ptr.h:268:4: note: in instantiation of member function 'std::default_delete<Data>::operator()' requested here
get_deleter()(__ptr);
^
8 : <source>:8:31: note: in instantiation of member function 'std::unique_ptr<Data, std::default_delete<Data> >::~unique_ptr' requested here
std::unique_ptr<Data> m = make_me();
^
3 : <source>:3:8: note: forward declaration of 'Data' …Run Code Online (Sandbox Code Playgroud) 我发现了使用多态C++ 14 lambdas(lambdas auto在其参数中)的奇怪行为:
小片0:
#include <iostream>
template<typename T> void doLambda(T&& mFn)
{
std::forward<T>(mFn)(int{0});
}
template<typename T> void test(T&& mV)
{
doLambda([&mV](auto mE)
{
std::forward<decltype(mV)>(mV);
});
}
int main() { test(int{0}); return 0; }
Run Code Online (Sandbox Code Playgroud)
clang ++ 3.5.1:代码片段编译并成功运行.
g ++ 4.9.2:代码片段无法编译:
example.cpp:实例化
'test(T&&)::<lambda(auto:1)> [with auto:1 = int; T = int]':5:从
'void doLambda(T&&) [with T = test(T&&) [with T = int]::]'
13要求:从'void test(T&&) [with T = int]'
18要求:从这里要求
12:错误:'mV'未在此范围内声明
std::forward<decltype(mV)>(mV);
^编译失败
小片1:
与代码段0的唯一区别在于 …
在使用编译时字符串(可变参数列表char)操作时,我需要实现一种检查编译时字符串是否包含另一个(较小的)编译时字符串的方法.
这是我的第一次尝试:
template<int I1, int I2, typename, typename> struct Contains;
template<int I1, int I2, char... Cs1, char... Cs2>
struct Contains<I1, I2, CharList<Cs1...>, CharList<Cs2...>>
{
using L1 = CharList<Cs1...>;
using L2 = CharList<Cs2...>;
static constexpr int sz1{L1::size};
static constexpr int sz2{L2::size};
using Type = std::conditional
<
(I1 >= sz1),
std::false_type,
std::conditional
<
(L1::template at<I1>() != L2::template at<I2>()),
typename Contains<I1 + 1, 0, L1, L2>::Type,
std::conditional
<
(I2 == sz2 - 1),
std::true_type,
typename Contains<I1 + 1, I2 + 1, …Run Code Online (Sandbox Code Playgroud) c++ templates metaprogramming template-meta-programming c++14