- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我写了自己的“插槽”又名“可调用包装器”,因为我想在其他对象上提供成员函数插槽重新绑定(bind)(即我需要一种方法来存储成员函数指针和指向相关类的指针)。
我运行了一个小型测试并发现我的系统(64 位 Linux)上的 std::function
是我的两倍(GCC/libstdc++)到三倍(Clang/libc++)自己实现了一个类似的类,大小为 16 字节。非成员函数和 lambda 的实现是这样的(const void*
第一个参数是为了与此处未显示的成员函数槽保持一致):
template<typename... ArgTypes>
class slot
{
public:
virtual ~slot() = default;
virtual void operator()(const void* object, ArgTypes...) const = 0;
protected:
slot() = default;
};
template<typename Callable, typename... ArgTypes>
class callable_slot : public slot<ArgTypes...>
{
public:
callable_slot(Callable function_pointer_or_lambda) : callable(function_pointer_or_lambda) {}
virtual void operator()(const void*, ArgTypes... args) const override { callable(args...); }
private:
Callable callable;
};
template<typename Callable>
class callable_slot<Callable> : public slot<>
{
public:
callable_slot(Callable function_pointer_or_lambda) : callable(function_pointer_or_lambda) {}
virtual void operator()(const void*) const override { callable(); }
private:
Callable callable;
};
template<typename Callable, typename... ArgTypes>
using function_slot = callable_slot<Callable, ArgTypes...>;
我知道像 target
这样的东西没有在这里实现,但我认为任何缺失的函数都不会增加对象的大小。
我要问的是:为什么 std::function
的大小比我上面的廉价实现大?
最佳答案
你的 function_slot
需要 Callable
和一组 args...
, 并返回一个继承自 slot<args...>
的类型用virtual operator()
.
要以多态方式将其用作值,您必须将其包装在智能指针中并将其存储在堆中,并且必须转发包装类 operator()
到 slot<args...>
一个。
std::function
对应于那个包装器,而不是你的slot
或 callable_slot
对象。
template<class...Args>
struct smart_slot {
template<class Callable> // add SFINAE tests here TODO! IMPORTANT!
smart_slot( Callable other ):
my_slot( std::make_unique<callable_slot<Callable, Args...>>( std::move(other) ) )
{}
void operator()( Args...args ) const {
return (*my_slot)(std::forward<Args>(args)...);
}
// etc
private:
std::unique_ptr<slot<Args...>> my_slot;
};
smart_slot
更接近std::function
比你的代码。至于std::function
就此而言,您编写的所有内容都是 std::function
用户的实现细节永远不会看到。
现在,这只需要 std::function
是一个指针的大小。 std::function
更大,因为它具有所谓的小对象优化。
它不只是存储一个智能指针,它本身还有一 block 内存。如果您传入的对象适合该内存块,它会就地构造该内存块,而不是进行堆分配。
std::function
对于简单的情况,例如传递函数指针,基本上是强制执行此操作的。质量实现适用于更大和更复杂的对象。 MSVC 对最大为两个 std::string
的对象执行此操作
这意味着如果你这样做:
std::function<void(std::ostream&)> hello_world =
[s = "hello world"s](std::ostream& os)
{
os << s;
};
hello_world(std::cout);
它不会对 std::function
的良好实现进行动态分配.
请注意,一些主要的图书馆供应商在这种情况下会进行动态分配。
关于c++ - 我的插槽类错过了 std::function 有什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41003983/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!