1

Shell在我的设计中,我有一个针对大量参数模板化的类(让它成为)。这些参数中的大多数是我在项目中定义的其他类,因为我为我的项目选择了基于策略的设计方法。

类声明看起来像这样:

template <class int_t, class float_t, class Pol1, class Pol2,..., class PolN>
class Shell : Pol1, Pol2,...,PolN

前两个参数是应使用的整数和浮点类型。其余参数是项目中定义的特定策略。

这种设计对我来说很方便,因为它可以避免很多运行时检查(我们的目标是运行时性能)。然而,每当他/她想要创建Shell类的实例时,输入一个包含 10 多个参数的列表是非常麻烦的(从用户的角度来看)。

出于这个原因,我选择将这个打字负担连同宏一起移到一个单独的文件中。首先,我将所有策略默认为宏:

template <class int_t, class float_t, class Pol1 = DEF_1, class Pol2 = DEF_2,..., class PolN = DEF_N>
class Shell : Pol1, Pol2,...,PolN

模板参数可以在单独的文件中作为宏提供,而不是在求解器的声明中。例如:

#include <shell.cpp>

#define DEF_1 example1
#define DEF_2 example2
...
#define DEF_N exampleN

int main(){
    Shell<int,double> MyShell();
    return 0;
    }

这样,实例化类只需要传递给模板参数(其他+10参数通过宏传递)。定义甚至可以移动到单独的文件中,如下所示:

#include <shell.cpp>
#include "define.hpp"

这只是一种解决方法,因此不必在每次创建类的实例时都提供 10 多个参数的参数列表。宏是迄今为止我发现的最好的解决方案。但是,我知道宏不是大多数 C++ 应用程序中的“推荐”解决方案。

出于这个原因,我想知道这是否是一个典型的问题,以及如何在没有宏的情况下克服它。我还想知道宏是否是一个“好的”解决方案,或者我是否应该不惜一切代价避免这种设计。我将不胜感激有关此主题的任何帮助/评论,因为我对 C++ 很陌生 :)

4

2 回答 2

1

使用别名似乎更好:

template <class int_t, class float_t>
using MyShell = Shell<int_t, float_t, MyPol1, MyPol2, ..., MyPolN>;
于 2018-04-30T12:27:30.877 回答
1

这是一个完全无宏的解决方案,允许默认设置和从默认设置单独更改策略(无需重新指定默认设置),并且可以轻松扩展:

struct DefaultPol1 {};
struct DefaultPol2 {};
struct DefaultPol3 {};

struct OtherPol1 {};
struct OtherPol2 {};
struct OtherPol3 {};

template<class Pol1 = DefaultPol1, class Pol2 = DefaultPol2, class Pol3 = DefaultPol3>
struct Config
{
    using P1 = Pol1;
    using P2 = Pol2;
    using P3 = Pol3;


    template <class NewPol1>
    using ChangePol1To = Config<NewPol1, Pol2, Pol3>;

    template <class NewPol2>
    using ChangePol2To = Config<Pol1, NewPol2, Pol3>;

    template <class NewPol3>
    using ChangePol3To = Config<Pol1, Pol2, NewPol3>;
};

using DefaultConfig = Config<>;


template <class int_t, class float_t, class C = DefaultConfig>
class Shell : C::P1, C::P2, C::P3
{};


void foo()
{
    using config = DefaultConfig::ChangePol3To<OtherPol3>::ChangePol1To<OtherPol1>;
    Shell<unsigned, double, config> myShell;
}

https://godbolt.org/g/uPrRhc(改进版,感谢@Jarod42!)
(如果将空结构定义更改为仅(前向)声明,编译器错误表明选择了正确的策略)。

命名可能会随着更多的上下文而改进。

于 2018-04-30T12:57:41.057 回答