来自不同ID类型的对象生成缓慢汇编

发布于 2025-01-31 15:13:37 字数 1614 浏览 3 评论 0原文

我有一个模板类,可以从ID生成对象实例。上下文是具有对象复制的网络代码。

下面的代码显示了我可以设法执行此操作的一种方法,但是它的编译非常慢的缺点。

谁知道实现我的示例显示的“更好”方法。 我不确定如何使这个问题更清楚,希望该代码能够说明自己。

我看过外部模板,但是我看不到如何将其应用于模板类中的模板功能。如果有人知道该怎么做,那将解决这个问题。

另外,解决myRegistersSimple的模棱两可问题的方法也将非常有帮助!

template<typename ID, typename Base>
class Register
{
public:
    void create(ID id) { m_types.at(id).second(); }
private:
    std::map<ID, std::function<std::unique_ptr<Base>(ID)>> m_types;
};

template<typename tag>
struct ID { int value; };

class ABase {};
class BBase {};
class CBase {};
using ID_A = ID<struct ID_A_TAG>;
using ID_B = ID<struct ID_B_TAG>;
using ID_C = ID<struct ID_C_TAG>;

class MyRegistersSimple :
    public Register<ID_A, ABase>,
    public Register<ID_B, BBase>,
    public Register<ID_C, CBase>
{
};

template<typename... Registers>
class MultiRegister : public Registers...
{
public:
    template<typename ID>
    void create(ID)
    {
        // lots of complex template code to find the correct Register from 'Registers...'
        // and call 'create' on it
        // this makes compilation very slow
    }
};

class MyRegistersComplex : public MultiRegister<
    Register<ID_A, ABase>,
    Register<ID_B, BBase>,
    Register<ID_C, CBase>>
{};

void test()
{
    MyRegistersSimple simple;
    simple.create(ID_A(0)); // -> ambiguous, doest not compile

    MyRegistersComplex complex;
    complex.create(ID_A(0)); // -> very slow compilation
}

I have a of templated class that can generate an object instance from an ID. The context is networking code with object replication.

The code below shows a way that I can manage to do this, but it has the drawback of beeing very slow in compilation.

Does anyone know a "better" way to achieve what my example shows.
I'm not sure how to make this question more clear, I hope the code speaks for itself.

I have looked at extern templates, but I do not see how to apply that to templated functions in templated classes. If anyone knows how to do that, that would solve the issue.

Alternatively a way to fix the ambiguous problem of MyRegistersSimple would also be greatly helpfull!

template<typename ID, typename Base>
class Register
{
public:
    void create(ID id) { m_types.at(id).second(); }
private:
    std::map<ID, std::function<std::unique_ptr<Base>(ID)>> m_types;
};

template<typename tag>
struct ID { int value; };

class ABase {};
class BBase {};
class CBase {};
using ID_A = ID<struct ID_A_TAG>;
using ID_B = ID<struct ID_B_TAG>;
using ID_C = ID<struct ID_C_TAG>;

class MyRegistersSimple :
    public Register<ID_A, ABase>,
    public Register<ID_B, BBase>,
    public Register<ID_C, CBase>
{
};

template<typename... Registers>
class MultiRegister : public Registers...
{
public:
    template<typename ID>
    void create(ID)
    {
        // lots of complex template code to find the correct Register from 'Registers...'
        // and call 'create' on it
        // this makes compilation very slow
    }
};

class MyRegistersComplex : public MultiRegister<
    Register<ID_A, ABase>,
    Register<ID_B, BBase>,
    Register<ID_C, CBase>>
{};

void test()
{
    MyRegistersSimple simple;
    simple.create(ID_A(0)); // -> ambiguous, doest not compile

    MyRegistersComplex complex;
    complex.create(ID_A(0)); // -> very slow compilation
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雾里花 2025-02-07 15:13:37

基本解决方案

通过将所有基础通过通过来范围:

// a helper to avoid copy pasting `using`s
template<typename... Registers> struct MultiRegister : Registers... { using Registers::create...; };

class MyRegisters : public MultiRegister<
    Register<ID_A, ABase>,
    Register<ID_B, BBase>,
    Register<ID_C, CBase>>
{};

void test() {
    MyRegisters registers;
    registers.create(ID_A(0)); // IDE shows that `Register<ID<ID_A_TAG>, ABase>` is chosen
}

我希望内置的过载分辨率比...复杂版本中的“许多复杂的模板代码”更快。

;

我不喜欢该手册注册&lt; id_a,abase&gt; id_x&lt; - &gt XBase dispatch和虚拟ID_x_tags,因此我删除了所有这些(如果将XBase用作id> id的模板参数是正是的)。然后注册&lt; id_a,abase&gt;register&lt; id_b,bbase&gt;

template<typename Base> using MakeRegister = Register<ID<Base>, Base>;

。 - 是一样的)

template<typename... Registers> struct MultiRegister : Registers... { using Registers::create...; };
template<typename... Bases> using MakeMultiRegister = MultiRegister<MakeRegister<Bases>...>;
class MyRegisters : public MakeMultiRegister<ABase, BBase, CBase> {};

Basic solution

Bring all the bases into scope via using:

// a helper to avoid copy pasting `using`s
template<typename... Registers> struct MultiRegister : Registers... { using Registers::create...; };

class MyRegisters : public MultiRegister<
    Register<ID_A, ABase>,
    Register<ID_B, BBase>,
    Register<ID_C, CBase>>
{};

void test() {
    MyRegisters registers;
    registers.create(ID_A(0)); // IDE shows that `Register<ID<ID_A_TAG>, ABase>` is chosen
}

I hope the built-in overload resolution is faster than "lots of complex template code" in the ...Complex version.

Offtopic improvement

I didn't like that manual Register<ID_A, ABase> ID_x <-> xBase dispatch and dummy ID_x_TAGs, so I removed all of that (if using xBase as the ID's template parameter is fine). Then Register<ID_A, ABase>, Register<ID_B, BBase> etc. become

template<typename Base> using MakeRegister = Register<ID<Base>, Base>;

and the code suggested above is just (test() omitted - it's the same)

template<typename... Registers> struct MultiRegister : Registers... { using Registers::create...; };
template<typename... Bases> using MakeMultiRegister = MultiRegister<MakeRegister<Bases>...>;
class MyRegisters : public MakeMultiRegister<ABase, BBase, CBase> {};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文