C++ 编程模板的风格
如果有选择,你会选择哪一个C++ 编程模板的风格,c++,templates,C++,Templates,如果有选择,你会选择哪一个 template<class CheckEveryNode<true>> struct X; or template<bool CheckEveryNode> struct X; 模板 结构X; 或 模板 结构X; 从设计师的角度来看,这并不明显,一方面,我们在实际代码中具有可读性: //taking first approach //somewhere in the code X<CheckEveryNode<
template<class CheckEveryNode<true>>
struct X;
or
template<bool CheckEveryNode>
struct X;
模板
结构X;
或
模板
结构X;
从设计师的角度来看,这并不明显,一方面,我们在实际代码中具有可读性:
//taking first approach
//somewhere in the code
X<CheckEveryNode<false>> x;
//采取第一种方法
//代码中的某个地方
X;
在第二方面,有更多的内容可供输入,有些人更喜欢:
//taking second approach
//somewhere in the code
X<false> x;//but here we don't really see immediately what the false means.
//采取第二种方法
//代码中的某个地方
X//但在这里,我们并没有立即看到虚假的含义。
因此,期待您的意见/建议第一种方法看起来很麻烦。在第一个没有令人信服的理由的情况下,我会选择第二个。至于可读性,第二个是可读的。事实上,第一种方法由于语法混乱而降低了可读性。第一种方法看起来很麻烦。在第一个没有令人信服的理由的情况下,我会选择第二个。至于可读性,第二个是可读的。事实上,第一个由于其hotchpotch语法而降低了可读性。我也喜欢第二个。我的理念是,如果不需要,为什么还要创建一个额外的类型呢?我也喜欢第二个。我的理念是,如果不需要,为什么要创建一个额外的类型?首先
template<class CheckEveryNode<true>>
struct X;
模板
结构X;
这是错误的,应该是
template<template<bool> CheckEveryNode>
struct X{};
模板
结构X{};
这需要您专门研究正确或错误条件:
// above is true case, below is false case
template<>
struct X<CheckEveryNode<false> >{};
//以上为真,以下为假
模板
结构X{};
或按以下方式使用部分专门化:
template<class CheckEveryNode>
struct X;
template<bool B>
struct X<CheckEveryNode<B> >{
// real implementation
};
模板
结构X;
模板
结构X{
//实际执行
};
除此之外,第二个更容易实现,也更容易阅读,因为它是“预期的”。当您提供模板参数时,您知道它的用途,不需要额外的结构。首先
template<class CheckEveryNode<true>>
struct X;
模板
结构X;
这是错误的,应该是
template<template<bool> CheckEveryNode>
struct X{};
模板
结构X{};
这需要您专门研究正确或错误条件:
// above is true case, below is false case
template<>
struct X<CheckEveryNode<false> >{};
//以上为真,以下为假
模板
结构X{};
或按以下方式使用部分专门化:
template<class CheckEveryNode>
struct X;
template<bool B>
struct X<CheckEveryNode<B> >{
// real implementation
};
模板
结构X;
模板
结构X{
//实际执行
};
除此之外,第二个更容易实现,也更容易阅读,因为它是“预期的”。当您提供模板参数时,您知道它的用途,不需要额外的结构。经常涉猎元编程,我只能推荐一种“详细”的方法,但我不太喜欢您提出的第一种方法 理想情况下,在使用策略时,您不仅要传递一个标志,还要传递一个策略对象,这将允许用户随意定制它,而不是依赖于您自己的预定义值 例如:
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 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;
...
};
模板
结构策略选择器
{
typedef/**/type;
};
模板
第X类:政策。。。
{
typedef typename PolicySelector::type NodeCheckerPolicy;
typedef typename策略选择器::类型NodeLocatorPolicy;
...
};
请注意,通过从策略继承,如果您只关心调用某些函数,那么选择可能是不必要的。只有当您需要隐藏在策略中的内部typedef时才有必要,因为它们应该在派生类中显式定义(此处为X)。经常涉猎元编程,我只能推荐一种“详细”的方法,但我不太喜欢您提出的第一种方法 理想情况下,在使用策略时,您不仅要传递一个标志,还要传递一个策略对象,这将允许用户随意定制它,而不是依赖于您自己的预定义值 例如:
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 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;
...
};
模板
结构策略选择器
{
typedef/**/type;
};
模板
第X类:政策。。。
{
typedef typename PolicySelector::type NodeCheckerPolicy;
typedef typename策略选择器::类型NodeLocatorPolicy;
...
};
请注意,通过从策略继承,如果您只关心调用某些函数,那么选择可能是不必要的。只有当您需要隐藏在策略中的内部typedef时才有必要,因为这些类型应该在派生类中显式定义(此处为X)。如果您关心的是当您有多个策略时会发生什么,并且您不知道各种布尔值的含义,那么您可以一起消除布尔值并使用标记
struct CheckEvery { };
struct CheckNone { };
template<typename Check> struct Thingy;
template<> Thingy<CheckEvery> { ... };
template<> Thingy<CheckNone> { ... };
struct CheckEvery{};
结构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); }
};
struct CheckEvery{bool shouldCheck(int){return true;}};
结构CheckNone{bool shouldCheck(int){返回false;}};
结构校验概率{bool shouldCheck(inti){返回i%2;};
模板结构{
检查者;
void someFunction(inti){if(checker.shouldCheck(i))check(i);}
};
这个例子没有很好地充实,但它给了你一个想法。例如,您可能希望为
Thingy
构造函数提供一个Checker
对象 如果您关心的是当您有多个策略时会发生什么,并且您不知道各种布尔值的含义,那么您可以一起消除布尔值并使用标记
struct CheckEvery { };
struct CheckNone { };
template<typename Check> struct Thingy;
template<> Thingy<CheckEvery> { ... };
template<> Thingy<CheckNone> { ... };
struct CheckEvery{};
结构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); }
};
struct CheckEve