【问题标题】:Most efficient way to implement template-based optional class members in C++?在 C++ 中实现基于模板的可选类成员的最有效方法是什么?
【发布时间】:2025-11-29 03:55:01
【问题描述】:

我有一个性能关键的应用程序,需要通过各种特征类来修改我的类的行为。一些更复杂的变体需要主类中的其他类成员。

所以我的问题是:根据所使用的特征类,提供此类成员的最有效方法是什么?

我想要的是这样的:

template <class Traits> MainClass {

    typedef typename Traits::MemberType MT;

public:
    MT my_member;

    void do_something() {
        std::cout << Traits::get_number(this) << std::endl;
    }

    ...

};

class Zero {
public:
    typedef void MemberType;

    static inline int get_number(MainClass<Zero>*) { return 0; }
}

class IntegerNumber {
public:
    typedef int MemberType;

    static inline int get_number(MainClass<IntegerNumber>* myclass) { return myclass->my_member; }
}

现在这不起作用,因为您不能声明变量 void。但由于我将拥有大量 MainClass 实例并且有许多不同的特征类,我不希望每个可能的特征都有“虚拟”变量。

实现这一点的一种可能性是通过继承,但这正是我想通过使用模板首先避免的,因为这会导致性能损失,尤其是在具有多个不同特征时。

所以我的问题是:

  1. 我可以告诉编译器消除类中某些未使用的成员变量吗?
  2. 您将如何解决这个问题?是否有其他可能实现这一点?
  3. 哪种方法最有效?

【问题讨论】:

  • AFAIK 你只能通过专门的模板或使用预处理器来做到这一点。
  • 没有多态性的继承是否会导致性能问题(我认为它已被编译器优化并且不会导致运行时开销,但我不确定)?
  • @NathanOliver 我想尽可能避免使用预处理器(无论如何它不能直接绑定到模板,对吧?)。在谈到模板专业化时,您是指 Sopel 提出的解决方案还是您有其他想法?
  • @nefas 我是这么认为的,但我不再那么确定了。可能有一个小的基类,这确实会被优化。

标签: c++ performance templates


【解决方案1】:

对于这个例子,这应该可以,但我不知道它是否足以满足您的需求。

#include <algorithm>
#include <iostream>
#include <vector>

template <class MemberType>
class MainClassBase
{
public:
    MemberType my_member;
};

template <>
class MainClassBase<void>
{
};

template <class Traits> 
class MainClass : public MainClassBase<typename Traits::MemberType> {

public:

    void do_something() {
        std::cout << Traits::get_number(this) << std::endl;
    }

};

class Zero {
public:
    typedef void MemberType;

    static inline int get_number(MainClass<Zero>*) { return 0; }
};

class IntegerNumber {
public:
    typedef int MemberType;

    static inline int get_number(MainClass<IntegerNumber>* myclass) { return myclass->my_member; }
};
class String {
public:
    typedef std::string MemberType;

    static inline std::string get_number(MainClass<String>* myclass) { return myclass->my_member; }
};

int main()
{
    MainClass<Zero> mainClassZero{};

    MainClass<IntegerNumber> mainClassInteger{};
    mainClassInteger.my_member = -1;

    MainClass<String> mainClassString{};
    mainClassString.my_member = "asd";

    mainClassZero.do_something();
    mainClassInteger.do_something();
    mainClassString.do_something();
}

演示:http://coliru.stacked-crooked.com/a/013aabb763149596

如果您的类型是标准布局,则必须优化空基类(在 C++11 和更高版本中)。如果不是,那么它仍然很有可能会被优化。

【讨论】:

  • 这看起来很有希望,尽管(据我所知)当类定义成员时,由于继承仍然会有一些开销。多继承在优化过程中会不会出现问题? (因为我将有几个不同的特征以及可能的其他成员)
  • 如果基类不是虚拟的,那么它应该得到优化。您始终可以通过查看程序集输出来进行检查。
  • @cero 非虚拟继承不会增加开销
最近更新 更多