小编Dim*_*nov的帖子

为什么 std::any 的实现使用函数指针 + 函数操作码,而不是虚拟表指针 + 虚拟调用?

GCCLLVM实现都在对象std::any中存储函数指针any,并使用Op/Action参数调用该函数来执行不同的操作。以下是 LLVM 中该函数的示例:

static void* __handle(_Action __act, any const * __this,
                          any * __other, type_info const * __info,
                          void const* __fallback_info)
    {
        switch (__act)
        {
        case _Action::_Destroy:
          __destroy(const_cast<any &>(*__this));
          return nullptr;
        case _Action::_Copy:
          __copy(*__this, *__other);
          return nullptr;
        case _Action::_Move:
          __move(const_cast<any &>(*__this), *__other);
          return nullptr;
        case _Action::_Get:
            return __get(const_cast<any &>(*__this), __info, __fallback_info);
        case _Action::_TypeInfo:
          return __type_info();
        }
        __libcpp_unreachable();
    }
Run Code Online (Sandbox Code Playgroud)

注意:这只是一个__handle函数,但每个实现中有两个这样的函数any:一个用于在内部分配的小对象(小缓冲区优化)any,一个用于在堆上分配的大对象。使用哪一个取决于对象中存储的函数指针的值any

在运行时选择两种实现之一并从预定义的方法列表中调用特定方法的能力本质上是虚拟表的手动实现。我想知道为什么要这样实施。简单地存储指向虚拟类型的指针不是更容易吗? …

c++ stl std c++17

10
推荐指数
1
解决办法
343
查看次数

如何在C++中实现适用于Linux和Windows的适配器框架

这是我想要做的:

我正在开发支持插件的跨平台IDE(Linux和Windows).我需要使用类似于Eclipse提供的适配器框架来支持可扩展性.有关详细信息,请参阅此处,但基本上我需要以下内容:

AdapteeAdapted是已经存在的,而我们是不允许以任何方式改变完全无关的类.我想创建一个AdapterManager有方法的类

template <class Adaptee, class Adapted> Adapted* adapt( Adaptee* object);
Run Code Online (Sandbox Code Playgroud)

这将创建Adapted给定实例的实例Adaptee.如何创建实例取决于必须注册的适配器函数AdapterManager.每个新插件都应该能够为任意类型提供适配器功能.

以下是我对可能解决方案的看法以及为什么它不起作用:

  • C++ 11的RTTI函数和type_info类提供了一种hash_code()方法,它为程序中的每种类型返回一个唯一的整数.看到这里.因此,AdapterManager可以简单地包含给定Adaptee的哈希码的映射,并且Adapter类返回指向适配器函数的函数指针.这使得adapt()上面的函数的实现变得微不足道:

    template <class Adaptee, class Adapted> Adapted* AdapterManager::adapt( Adaptee* object)
    {
      AdapterMapKey mk( typeid(Adapted).hash_code(), typeid(Adaptee).hash_code());
      AdapterFunction af = adapterMap.get(mk);
      if (!af) return nullptr;
      return (Adapted*) af(object);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    任何插件都可以通过简单地在地图中插入附加功能来轻松扩展框架.另请注意,任何插件都可以尝试使任何类适应任何其他类,并且如果存在相应的适配器函数,则AdapterManager无论注册者是谁,都会成功.

  • 这个问题是模板和插件(共享对象/ DLL)的组合.由于两个插件可以使用相同的参数实例化模板类,因此可能会导致相应type_info结构的两个单独实例以及可能不同的hash_code()结果,这将破坏上述机制.从一个插件注册的适配器功能可能并不总是在另一个插件中工作.
  • 在Linux中,动态连接器似乎是能够处理的在根据某些条件下不同的共享库类型的多个声明(点4.2).然而真正的问题是在Windows中,似乎每个DLL都将获得自己的模板实例化版本,无论它是否也在其他加载的DLL或主可执行文件中定义.与Linux中使用的动态链接器相比,动态链接器似乎非常不灵活.
  • 我已经考虑使用显式模板实例化,这似乎可以减少问题,但仍然无法解决它,因为两个不同的插件可能仍然以相同的方式实例化相同的模板.

问题: …

c++ dll templates cross-platform shared-libraries

9
推荐指数
1
解决办法
567
查看次数

C++找不到继承自当前模板类的模板基类中定义的类型

我正在尝试编写定义super类型习惯用法模板类的变体.该类Inherit引入了类型Super来表示可能非常长的超类型,并且还需要知道派生类型New来做一些我没有在这里展示的额外的东西.

如果传递给的类型New不是模板,但是模板失败,则此方法正常.这是一个用clang++-3.8 -std=c++1y -Wall(gcc给出相同的输出)编译的完整示例:

struct SomeBase {};

template<class New, class Base>
struct Inherit : Base {
    using Super = Inherit<New, Base>;
};

struct NonTemplate : Inherit<NonTemplate, SomeBase> {
    using X = Super;
    // compiles and is nice and short
};

template<class T>
struct Template : Inherit<Template<T>, SomeBase>
{
    using A = Super;
    // error: unknown type name 'Super'; did you mean 'NonTemplate::Super'?

    using B …
Run Code Online (Sandbox Code Playgroud)

c++ templates super crtp typename

2
推荐指数
1
解决办法
671
查看次数

标签 统计

c++ ×3

templates ×2

c++17 ×1

cross-platform ×1

crtp ×1

dll ×1

shared-libraries ×1

std ×1

stl ×1

super ×1

typename ×1