我在理解函数类型时遇到问题(它们看起来像是a的Signature模板参数std::function):
typedef int Signature(int); // the signature in question
typedef std::function<int(int)> std_fun_1;
typedef std::function<Signature> std_fun_2;
static_assert(std::is_same<std_fun_1, std_fun_2>::value,
"They are the same, cool.");
int square(int x) { return x*x; }
Signature* pf = square; // pf is a function pointer, easy
Signature f; // but what the hell is this?
f(42); // this compiles but doesn't link
Run Code Online (Sandbox Code Playgroud)
变量f无法分配,但可以调用.奇怪的.那有什么好处呢?
现在,如果我对typedef进行const限定,我仍然可以使用它来构建更多类型,但显然没有别的:
typedef int ConstSig(int) const;
typedef std::function<int(int) const> std_fun_3;
typedef std::function<ConstSig> std_fun_4;
static_assert(std::is_same<std_fun_3, std_fun_4>::value,
"Also the same, …Run Code Online (Sandbox Code Playgroud) 我想知道是否unordered_map使用类型擦除实现,因为unordered_map<Key, A*>并且unordered_map<Key, B*>可以使用完全相同的代码(除了强制转换,这是机器代码中的无操作).也就是说,两者的实现可以基于unordered_map<Key, void*>保存代码大小.
更新:此技术通常被称为精简模板成语(感谢下面的评论者指出这一点).
更新2:我对Howard Hinnant的观点特别感兴趣.我希望他读到这个.
所以我写了这个小测试:
#include <iostream>
#if BOOST
# include <boost/unordered_map.hpp>
using boost::unordered_map;
#else
# include <unordered_map>
using std::unordered_map;
#endif
struct A { A(int x) : x(x) {} int x; };
struct B { B(int x) : x(x) {} int x; };
int main()
{
#if SMALL
unordered_map<std::string, void*> ma, mb;
#else
unordered_map<std::string, A*> ma;
unordered_map<std::string, B*> mb;
#endif
ma["foo"] = new …Run Code Online (Sandbox Code Playgroud) 在RPC通信协议中,在调用方法之后,我将"完成"消息发送回调用者.由于以并发方式调用方法,因此包含响应(a std::string)的缓冲区需要由互斥锁保护.我想要实现的目标如下:
void connection::send_response()
{
// block until previous response is sent
std::unique_lock<std::mutex> locker(response_mutex_);
// prepare response
response_ = "foo";
// send response back to caller. move the unique_lock into the binder
// to keep the mutex locked until asio is done sending.
asio::async_write(stream_,
asio::const_buffers_1(response_.data(), response_.size()),
std::bind(&connection::response_sent, shared_from_this(),
_1, _2, std::move(locker))
);
}
void connection::response_sent(const boost::system::error_code& err, std::size_t len)
{
if (err) handle_error(err);
// the mutex is unlocked when the binder is destroyed
}
Run Code Online (Sandbox Code Playgroud)
但是,这无法编译,因为boost::asio需要处理程序是CopyConstructible. …
不知怎的,我不知道如何扩展可变参数模板参数包.以下代码有什么问题?
#include <iostream>
template <typename T>
struct print_one
{
static void run(const T& t)
{
std::cout << t << ' ';
}
};
template<typename... Args>
void print_all(Args&&... args)
{
// the next line doesn't compile:
print_one<Args>::run(std::forward<Args>(args))...;
}
int main()
{
print_all(1.23, "foo");
}
Run Code Online (Sandbox Code Playgroud)
Clang说,Expression contains unexpanded parameter packs 'Args' and 'args'.为什么?
我正在使用Howard Hinnant很好的基于竞技场的小分配器,short_alloc.
让我感到震惊的是,从一个已经超出其竞技场并因此在堆上分配的向量进行移动分配可以使用通常的快速移动分配(即,抓取目标的资源)来完成.然而,这种情况并非如此:
typedef arena<16> arena_type;
typedef short_alloc<int, 16> alloc_type;
typedef std::vector<int, alloc_type> vec_type;
arena_type arena1, arena2;
vec_type vec1(alloc_type(arena1)), vec2(alloc_type(arena2));
vec1.resize(100);
void* data = vec1.data();
vec2 = std::move(vec1);
assert(vec2.data() == data); // fails
Run Code Online (Sandbox Code Playgroud)
正如在这个答案中所解释的,这是由于向量的移动赋值运算符比较了两个分配器(注意propagate_on_container_move_assignment就是这样std::false_type).由于两个分配器不比较相等(因为它们具有不同的竞技场),目标向量需要分配内存并逐个移动值.
通过将等于运算符更改为,可以实现所需的行为
template <class T1, size_t N1, class T2, size_t N2>
bool operator==(const short_alloc<T1, N1>& x, const short_alloc<T2, N2>& y) noexcept
{
return N1 == N2 && (&x.a_ == &y.a_ || y.a_.on_heap());
}
Run Code Online (Sandbox Code Playgroud)
其中,on_heap()如果分配没有使用它的竞技场检查.
这个解决方案看起来相当hackish(注意例如,平等不对称),我可以/我会通过这样做射击自己吗?有优雅的解决方案吗?
在我的代码中,我需要测试给模板的类型是否是指针 - 无论是否聪明.根据提升,没有可靠和通用的方法(见这里) - 或者有吗?
到目前为止,我检查以下内容:
T转换为void*?T有get()方法吗?T没有叫做element_type?get()回来了element_type*吗?如果(A || B && C && D),那么我得出结论,我的类型必须是某种指针.
这是模板:
template <typename T>
class is_pointer_type
{
typedef struct { char array[1]; } yes;
typedef struct { char array[2]; } no;
template <typename C> static yes test_g(decltype(&C::get));
template <typename C> static no test_g(...);
template <typename C> static yes test_e(typename C::element_type*);
template <typename C> static …Run Code Online (Sandbox Code Playgroud) 附加延续时boost::future,继续在新线程中执行:
std::cout << "main: " << boost::this_thread::get_id() << std::endl;
boost::promise<void> p;
boost::future<void> f = p.get_future();
p.set_value();
boost::future<void> f2 = f.then([] (boost::future<void>) {
std::cout << "future: " << boost::this_thread::get_id() << std::endl;
});
Run Code Online (Sandbox Code Playgroud)
此代码段输出:
main: 0x7fff7a8d7310
future: 0x101781000
Run Code Online (Sandbox Code Playgroud)
为什么.then()允许这样做,更重要的是,有没有办法来定制这种行为?不要future从返回S ^ promise/ packaged_task/ async不同的表现?
我需要在类中存储通用引用(我确信引用的值将比类更长).这样做有规范的方法吗?
这是我想出的最小例子.它似乎有效,但我不确定我是否做对了.
template <typename F, typename X>
struct binder
{
template <typename G, typename Y>
binder(G&& g, Y&& y) : f(std::forward<G>(g)), x(std::forward<Y>(y)) {}
void operator()() { f(std::forward<X>(x)); }
F&& f;
X&& x;
};
template <typename F, typename X>
binder<F&&, X&&> bind(F&& f, X&& x)
{
return binder<F&&, X&&>(std::forward<F>(f), std::forward<X>(x));
}
void test()
{
int i = 1;
const int j = 2;
auto f = [](int){};
bind(f, i)(); // X&& is int&
bind(f, j)(); // X&& is const int&
bind(f, …Run Code Online (Sandbox Code Playgroud) 调用嵌套std::bind表达式时遇到问题.以下代码演示了此问题.它无法使用libc ++进行编译,但可以使用boost:
#define BOOST 0
#if BOOST
#include <boost/function.hpp>
#include <boost/bind.hpp>
using boost::function;
using boost::bind;
#else
#include <functional>
using std::function;
using std::bind;
using std::placeholders::_1;
#endif
int sum(int a, int b) { return a+b; }
// works
template <typename F>
int yeah(F f, int c)
{
return f(c);
}
// breaks with libc++
template <typename F>
int nope(F f, int c)
{
return bind(f, c)();
}
// fixes the problem
template <typename F>
int fix1(F f, int c)
{ …Run Code Online (Sandbox Code Playgroud) c++ ×9
c++11 ×7
boost ×3
templates ×3
libc++ ×2
allocator ×1
boost-asio ×1
boost-bind ×1
shared-ptr ×1
std-function ×1
type-erasure ×1