基类模板参数的有意义的名称

时间:2018-04-27 08:01:56

标签: c++

命名基类非类型参数的最佳方法是什么,如

class Derived : public Base<Argument> {
...
}

如果我能做到这一点会很棒:

class Derived : public Base<Argument> {
  constexpr static int Argument = 1;
...
}

但是在Derived的类声明中没有定义Argument。

我可以使用#define,但我也希望将此名称嵌入到命名空间中。

以下讨论说明标准做法是

template<int N>
class Base {
protected:
  static const int n = N;
  ...
};

并使用&#34; n&#34;作为需要此值的有意义的名称。

Using template argument of base class in derived class

但是,值本身在派生类声明中看起来是加密的:

class Derived : public Base<whatever value>

这种方法是最好的选择吗?

编辑:我的动机是为将来的其他开发人员修改这个论点。他们更容易修改这条线&#34; BufferSize = 1024&#34;在

class MyScreen : public ScreenBase<BufferSize> {
    ... BufferSize = 1024;

而不是

class MyScreen : public ScreenBase<1024> {

1 个答案:

答案 0 :(得分:0)

使用虚构的名称很难推理,但是,如果我理解正确的话,你想要有模板参数的名称(例如快速搜索和替换它们)。

我不认为这是一个大问题,每次Base<T>用作基类时都可以搜索(即使是grep的简单天真public Base<也会这样做。由于某些原因你不想这样做,并且你不能放弃模板而支持属性或ctor参数,那么你只需要为你的值引入一个命名容器: / p>

#include <type_traits>
#include <cstddef>

template<std::size_t V>
struct buffer_size : public std::integral_constant<std::size_t, V> {};

现在您的班级声明将是:

template<typename S>
struct buffered_stream<S> {
   static constexpr std::size_t size = S::value;
};

现在,当您使用它时,您可以清楚地了解参数是什么:

struct network_stream : public buffered_stream<buffer_size<1024>> {
   // ...
};

请注意,这在某种程度上受到模板实例化方法的启发,例如,您可以在std::chrono::duration中看到。出于同样的原因,您还应该考虑使用用户定义的后缀(当它们足够清晰时)。例如,在许多情况下这可能就足够了:

struct network_stream : public buffered_stream<1024_bytes> {
   // ...
};

请将此代码视为一个起点,当然您希望使用std::is_same()来生成一些不错的编译器诊断程序(特别是如果您有多个命名的参数)。仅这一点就会使你的代码比这个概念证明更复杂,但我想你现在明白了如何去做。