首页 > 解决方案 > 具有常量模板的静态多态性

问题描述

我希望父类具有模板std::array大小的静态多态性。此代码工作正常:

#include <iostream>
#include <array>

using namespace std;

template <size_t size>
class Message
{
  public:
    size_t GetSize() { return size; }
  private:
    std::array<uint8_t, size> data_{};
};

class Command : public Message<12>
{
  public:
    static const size_t kCmdSize{12};
  private:
};

class Reply : public Message<16>
{
  public:
    static const size_t kCmdSize{12};
  private:
};

int main()
{
    Command cmd{};
    Reply rpl{};
    cout << "Size: " << cmd.GetSize() << "|" << rpl.GetSize() << endl;
    return 0;
}

但我不是幻数的忠实粉丝。

有没有办法使用子类中声明的常量作为父类的参数?像这样的东西:

class Command : public Message<kCmdSize>
{
  public:
    static const size_t kCmdSize{12};
  private:
};

直接使用它会尝试使用尚不存在的类中的变量。使用 C++14。

标签: c++c++11c++14

解决方案


如果您对额外的间接层没问题,那么您可以使用“特征类”类型的解决方案:

#include <array>
#include <cstdint>

template <class T> struct MessageSize;

template <std::size_t size>
class Message {
  public:
    std::size_t GetSize() { return size; }

  private:
    std::array<std::uint8_t, size> data_{};
};

// Forward declare class for upcoming specialization.
class Command;

// Specialize message size for Command class.
template <> struct MessageSize<Command> {
  static constexpr std::size_t size = 12;
};

class Command : public Message<MessageSize<Command>::size> { };

请注意,在我的示例中,Message该类本身不使用该类MessageSize。您也可以这样做,并改为Command继承自Message<Command>,但这会使您的继承树看起来完全不同(即具有相同消息长度的类将不再具有相同的基类)。

您当然可以在其中添加另一层间接,您可以在其中继承例如MessageBase<Command>,而后者又继承自Message<MessageSize<Command>::size>.


推荐阅读