编程模板的风格
Style of programming templates
如果可以选择,你会选择哪一个?
template<class CheckEveryNode<true>>
struct X;
or
template<bool CheckEveryNode>
struct X;
从设计人员的角度来看,这并不明显,一方面我们在实际代码中具有可读性:
//taking first approach
//somewhere in the code
X<CheckEveryNode<false>> x;
在另一边有更多的东西要输入,有人更喜欢:
//taking second approach
//somewhere in the code
X<false> x;//but here we don't really see immediately what the false means.
所以,期待你的意见/建议
经常涉水元编程,我只能推荐一种"冗长"的方法,但我不太喜欢您提出的第一种方法。
理想情况下,当使用Policy时,您不只是传递一个标志,而是传递一个Policy对象,它允许用户随意自定义它,而不是依赖于您自己的预定义值。
例如:struct NodeCheckerTag {};
struct CheckEveryNode {
typedef NodeCheckerTag PolicyTag;
void check(List const& list);
};
struct CheckFirstNode {
typedef NodeCheckerTag PolicyTag;
void check(List const& list);
};
template <typename Rand>
struct CheckSomeNodes {
typedef NodeCheckerTag PolicyTag;
CheckSomeNodes(Rand rand): _rand(rand) {}
void check(List const& list);
Rand _rand;
};
你的类应该允许用户选择选择哪个策略:
template <typename NodeChecker>
class X: NodeChecker // allow stateful implementation but let EBO kick in
{
};
PolicyTag
用于多个策略的存在:
template <typename NodeChecker, typename NodeAllocator, typename NodeNotifier>
class X;
你通常应该提供合理的默认值,但总是有的情况下,我想自定义只是最后一个!,通过切换到可变的模板,你可以得到:
template <typename Tag, typename Default, typename... Policies>
struct PolicySelector
{
typedef /**/ type;
};
template <typename... Policies>
class X: Policies...
{
typedef typename PolicySelector<NodeCheckerTag, CheckNoNode,
Policies...>::type NodeCheckerPolicy;
typedef typename PolicySelector<NodeAllocatorTag, StdAllocator,
Policies...>::type NodeAllocatorPolicy;
...
};
注意,通过从策略继承,如果您只关心调用某些函数,那么选择可能是不必要的。只有在需要隐藏在策略中的内部类型时才需要这样做,因为这些类型应该在派生类(这里的X)中显式地定义。
First
template<class CheckEveryNode<true>>
struct X;
是错的,应该是
template<template<bool> CheckEveryNode>
struct X{};
将需要您专门化true或false条件:
// above is true case, below is false case
template<>
struct X<CheckEveryNode<false> >{};
或者以以下方式使用部分专门化:
template<class CheckEveryNode>
struct X;
template<bool B>
struct X<CheckEveryNode<B> >{
// real implementation
};
除此之外,第二个更容易实现,也更容易阅读,因为它是"预期的"。当您提供模板参数时,您知道它的用途,不需要额外的结构体。
如果您关心的是当您有多个策略时发生的情况,并且您不知道各种布尔值的含义,则可以将布尔值全部消除并使用标记。
struct CheckEvery { };
struct CheckNone { };
template<typename Check> struct Thingy;
template<> Thingy<CheckEvery> { ... };
template<> Thingy<CheckNone> { ... };
或者你可以让策略来决定要做的工作,而不是专门化。
struct CheckEvery { bool shouldCheck(int) { return true; } };
struct CheckNone { bool shouldCheck(int) { return false; } };
struct CheckOdds { bool shouldCheck(int i) { return i % 2; } };
template<typename Checker> struct Thingy {
Checker checker;
void someFunction(int i) { if(checker.shouldCheck(i)) check(i); }
};
这个例子没有很好地具体化,但它给了你一个想法。例如,您可能希望向Thingy
构造函数提供Checker
对象。
我也喜欢第二个。我的哲学是,如果你不需要,为什么要创建一个额外的类型?
第一种方法看起来很麻烦。我会选择第二种,因为第一种没有令人信服的理由。至于可读性,第二个是可读的。事实上,第一种格式由于其语法的大杂烩而降低了可读性。
- Qt VTK交互风格的信号到小部件
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 我可以使用条件运算符初始化C风格的字符串文字吗
- Visual Studio 2019:插入多个C++风格的单行注释
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 如何在本地机器上运行c++和javascript客户端代码(hackerbank风格)
- 模板元编程:如何将参数包组合成新的参数包
- 以C++元编程风格实现 RLE 算法
- C++宏中的函数式编程风格:这是否记录在任何地方
- 为什么除了编程风格之外还使用成语"Reference to pointer"?
- C++方法良好的编程风格
- 如何以"functional"编程风格显示 QImage
- 面向对象编程风格
- 内存泄漏C++.编程风格
- 浮点运算的编程风格
- "Game Coding Complete"的编程风格
- 正确使用智能指针和编程风格
- 编程风格:对象与引用或值通道?(c++)
- 编程风格-如何使用clang-format缩进c++ pragma
- 编程模板的风格