我有兴趣探索实时多人客户端 - 服务器游戏开发和相关算法.很多着名的多人游戏如Quake 3或Half-Life 2都使用增量压缩技术来节省带宽.
服务器必须不断向所有客户端发送最新的游戏状态快照.总是发送完整快照会非常昂贵,因此服务器只发送最后一个快照和当前快照之间的差异.
......好吗,对吗?好吧,我发现很难想到的部分是如何实际计算两种游戏状态之间的差异.
游戏状态可能非常复杂,并且在堆上分配的实体通过指针相互引用,可以具有表示从架构到另一个不同的数值,以及更多.
我发现很难相信每个游戏对象类型都有一个手写的序列化/反序列化/差异计算功能.
让我们回到基础.假设我有两个状态,用位表示,我想计算它们之间的区别:
state0: 00001000100 // state at time=0
state1: 10000000101 // state at time=1
-----------
added: 10000000001 // bits that were 0 in state0 and are 1 in state1
removed: 00001000000 // bits that were 1 in state0 and are 1 in state1
Run Code Online (Sandbox Code Playgroud)
太好了,我现在有了added和removed diff的bitsets - 但是......
...差异的大小仍然与州的大小完全相同.而且我实际上必须通过网络发送两个差异!
一个有效的策略实际上是从那些diff位集构建某种稀疏数据结构吗?例:
// (bit index, added/removed)
// added = 0 …Run Code Online (Sandbox Code Playgroud) algorithm serialization network-programming client-server delta
我正在尝试使用libc ++,libc ++ abi和clang ++ 3.6.0在Arch Linux x64上编译我的项目.
项目编译正确,但无法链接以下错误:
错误:CMakeFiles/main.cpp.o:对符号'__cxa_thread_atexit @@ CXXABI_1.3.7'的未定义引用
/usr/lib/libstdc++.so.6: - 1:错误:添加符号时出错:命令行中缺少DSO
我正在使用-stdlib=libc++ -lc++abi标志进行编译和链接.
我应该链接哪些额外的库?我错过了一面旗帜吗?
我正在尝试编写一个函数,该函数以一个形式返回一个可变参数包的子集std::tuple.理想情况下,该函数不应具有运行时开销(没有不必要的副本),并且应该允许用户访问lvalue引用并修改它们.
应保持值类型,lvalue引用和const lvalue引用.Temporaries(rvalue引用)应该"转换"为值类型,以避免创建无效引用(对临时引用的引用).
期望结果的示例:
int lr = 5;
const int& clr = lr;
auto t = make_subpack_tuple(lr, clr, 5);
static_assert(is_same
<
decltype(t),
std::tuple<int&, const int&, int>
>{}, "");
// Ok, modifies lr:
std::get<0>(t) = 10;
// Compile-time error, intended:
// std::get<1>(t) = 20;
// Ok, 5 was moved into the tuple:
std::get<2>(t) = 30;
Run Code Online (Sandbox Code Playgroud)
示例不完整实施:
template<typename... Ts>
auto make_subpack_tuple(Ts&&... xs)
{
return std::tuple
<
some_type_trait<decltype(xs)>...
>
(
std::forward<decltype(xs)>(xs)...
);
} …Run Code Online (Sandbox Code Playgroud) 我创建了一个简单的类型特征来删除右值引用:
template <typename T>
struct remove_rvalue_reference { using type = T; };
template <typename T>
struct remove_rvalue_reference<T&&> { using type = T; };
template <typename T>
using remove_rvalue_reference_t =
typename remove_rvalue_reference<T>::type;
Run Code Online (Sandbox Code Playgroud)
我用它来实现一个copy_if_rvalue(x)函数,其返回类型取决于传递的参数:
template <typename T>
constexpr auto copy_if_rvalue(T && x)
-> remove_rvalue_reference_t<decltype(std::forward<decltype(x)>(x))>
{
return std::forward<decltype(x)>(x);
}
Run Code Online (Sandbox Code Playgroud)
为了确保函数返回正确的类型,我编写了一些简单的静态断言:
// literal
static_assert(std::is_same<
decltype(copy_if_rvalue(0)), int
>{});
// lvalue
int lv = 10;
static_assert(std::is_same<
decltype(copy_if_rvalue(lv)), int&
>{});
// const lvalue
const int clv = 10;
static_assert(std::is_same<
decltype(copy_if_rvalue(clv)), const int& …Run Code Online (Sandbox Code Playgroud) 我在我的一个真实项目中遇到了一个难以调试的情况,我不小心访问了已被移动的lambda中的局部变量的引用.访问是从另一个线程完成的,但移动的lambda保持活着直到第二个线程完成.
该错误仅在禁用优化时发生,并且是由粗心重构引起的.
我创建了一个最小的例子(可在wandbox上找到),它可以重现这个问题:
struct state
{
int x = 100;
};
template <typename TF>
void eat1(TF&& f)
{
// Call the lambda.
f();
// Simulate waiting for the second thread
// to finish.
std::this_thread::sleep_for(1000ms);
}
template <typename TF>
void eat0(TF&& f)
{
// Move the lambda to some other handler.
eat1(std::forward<TF>(f));
}
void use_state(state& s)
{
// Will print `100`.
std::cout << s.x << "\n";
// Separate thread. Note that `s` is captured by
// reference. …Run Code Online (Sandbox Code Playgroud) 我试图boost::variant使用不完整的包装类和std::vector我的间接技术来定义和访问"递归" .我的实现适用于libstdc ++,但不适用于libc ++.
这是我定义我的变体的方式:
struct my_variant_wrapper;
using my_variant_array = std::vector<my_variant_wrapper>; // <- indirection here
using my_variant = boost::variant<int, my_variant_array>;
struct my_variant_wrapper
{
my_variant _v;
template <typename... Ts>
my_variant_wrapper(Ts&&... xs) : _v(std::forward<Ts>(xs)...) { }
};
Run Code Online (Sandbox Code Playgroud)
我std::vector用来引入间接(因此动态分配将阻止my_variant具有无限大小).
由于纸张N4510 ("标准容器的最小不完全类型支持")std::vector<my_variant_wrapper>,我非常有信心我可以使用,哪里my_variant_wrapper是不完整的类型:
根据WG21的2015年页面,该论文获得批准.
根据此页面,libstdc ++始终支持这些功能.
根据这个页面,它在libc ++ 3.6中实现.
我随后访问该变体如下:
struct …Run Code Online (Sandbox Code Playgroud) 我试图constexpr通过方法更改对象成员的值但我不明白为什么它不适用于这种特定情况:
#include <iostream>
struct test
{
int m_counter = 0;
constexpr test()
{
m_counter++;
m_counter++;
increment();
increment();
increment();
}
constexpr void increment()
{
m_counter++;
}
constexpr int value() const
{
return m_counter;
}
};
template<int value>
constexpr void check()
{
std::cout << value << std::endl;
}
// constexpr test t; // value = 3, why ?
int main()
{
constexpr test t; // value = 5, ok
check<t.value()>();
}
Run Code Online (Sandbox Code Playgroud)
当我在全局范围内创建对象时,我不明白为什么值为3.msvc和clang在两种情况下都显示5但不是gcc.谁错了?
考虑以下可变参数类模板:
template <typename... Ts>
struct foo
{
template <typename... Us>
foo(Us...) { }
};
Run Code Online (Sandbox Code Playgroud)
如果我尝试以foo下列方式实例化,g ++(trunk)和clang ++(trunk)都很高兴:
auto o = foo{};
Run Code Online (Sandbox Code Playgroud)
auto o = foo();
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)error: cannot deduce template arguments for 'foo' from () auto o = foo(); ^
{}()
这也适用于适当的演绎指南:https: //godbolt.org/g/qReXpM.
c++ language-lawyer variadic-templates template-argument-deduction c++17
考虑以下程序:
int i{0};
std::experimental::barrier b{2};
int main()
{
std::thread t0{[] {
b.arrive_and_wait();
std::cout << i << '\n';
}};
std::thread t1{[] {
i = 2;
b.arrive_and_wait();
}};
t0.join();
t1.join();
}
Run Code Online (Sandbox Code Playgroud)
这个程序是否保证打印出来2,即使i它不是原子变量?
根据cppreference:
调用
arrive_and_wait与屏障完成阶段的开始同步.完成阶段的完成与呼叫的返回同步.呼叫
arrive_and_drop并且arrive_and_wait永远不会与他们自己或彼此引入数据竞赛.
这表明每次arrive_and_wait调用都有一个同步点.但是我不确定是否允许编译器重新排序读/写操作i,因为它是非原子的.
Consider the following code snippet:
template <typename>
struct X { };
extern template struct X<int>;
int main()
{
X<int>{};
}
Run Code Online (Sandbox Code Playgroud)
It compiles and links: live example on godbolt.org. I would expect it not to link due to the extern template declaration.
My understanding is that extern template means: "please don't instantiate this particular template specialization in this TU, it will be provided by some other TU and you can link against it".
The examples/descriptions. I've seen on isocpp …