Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在模板参数列表较大的情况下方便使用宏_C++_Templates_Macros_Policy Based Design - Fatal编程技术网

C++ 在模板参数列表较大的情况下方便使用宏

C++ 在模板参数列表较大的情况下方便使用宏,c++,templates,macros,policy-based-design,C++,Templates,Macros,Policy Based Design,在我的设计中,我有一个类(让它成为Shell),它是根据大量参数模板化的。这些参数中的大多数是我在项目中定义的其他类,因为我为我的项目选择了基于策略的设计方法 类声明如下所示: template <class int_t, class float_t, class Pol1, class Pol2,..., class PolN> class Shell : Pol1, Pol2,...,PolN 模板参数可以作为宏在单独的文件中提供,而不是在解算器的声明中提供。例如: #incl

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

类声明如下所示:

template <class int_t, class float_t, class Pol1, class Pol2,..., class PolN>
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;
    }
#包括
#定义DEF_1示例1
#定义DEF_2示例2
...
#定义定义示例N
int main(){
Shell MyShell();
返回0;
}
这样,实例化类只需要传递给模板参数(其他+10个参数通过宏传递)。定义甚至可以移动到单独的文件中,如:

#include <shell.cpp>
#include "define.hpp"
#包括
#包括“define.hpp”
这只是一种变通方法,因此不必每次创建类实例时都提供10+个参数的参数列表。宏是迄今为止我找到的最好的解决方案。但是,我知道宏在大多数C++应用程序中不是一个“推荐”的解决方案。
出于这个原因,我想知道这是否是一个典型的问题,以及没有宏如何克服它。我还想知道宏是否是一个“ok”解决方案,或者我是否应该不惜一切代价避免这种设计。我很感谢这个主题的任何帮助/评论,因为我对C++是全新的:

使用别名似乎更好:

template <class int_t, class float_t>
using MyShell = Shell<int_t, float_t, MyPol1, MyPol2, ..., MyPolN>;
模板
使用MyShell=Shell;

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

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;
}
struct DefaultPol1{};
结构DefaultPol2{};
结构DefaultPol3{};
结构OtherPol1{};
结构OtherPol2{};
结构OtherPol3{};
模板
结构配置
{
使用P1=Pol1;
使用P2=Pol2;
使用P3=Pol3;
模板
使用ChangePol1To=Config;
模板
使用ChangePol2To=Config;
模板
使用ChangePol3To=Config;
};
使用DefaultConfig=Config;
模板
类外壳:C::P1、C::P2、C::P3
{};
void foo()
{
使用config=DefaultConfig::ChangePol3To::ChangePol1To;
壳壳;
}
(改进版,感谢@Jarod42!)
(如果将空结构定义更改为仅(正向)声明,编译器错误将显示选择了正确的策略)


命名可能会随着上下文的增加而改进。

您的示例无法构建。如果包含顺序与您指定的相同,则不会替换这些宏。或者,如果
#define
通常排在第二位。您可以在单个
typename策略集内设置它们的类型别名,而不是使用
Pol1..Poln
模板参数:避免包含cpp文件:
#include
,.hpp、.inl、.hxx将是更好的扩展。
Shell MyShell():麻烦解析:函数声明,您可能需要
Shell MyShell{}
Shell MyShell相反。嗨@HolyBlackCat,这里的别名是什么意思?你是说@Jarod42提出的解决方案吗?或者更像@MaxLanghof的解决方案?我比我更喜欢这个解决方案:)不过,这个解决方案只适用于宏,对吗?不需要宏,只需使用具体和预期的策略定义别名一次。我明白了!好的,这是我现在的方法,但是我想让用户不用编写长模板参数列表(代码的第二行)。我正试图找出如何将其作为一个选项列表(如我的原始帖子中的
default
s)来完成,而不是一个模板参数列表(最重要的是,参数的顺序非常重要),使用
代码编写
,或者宏列表曾经从用户的角度看起来很相似……也许你是对的,我试图删除“helper”(别名)是一种过分的尝试。我应该再考虑一下:)我非常喜欢使用
struct Config
来指定选项。事实上,我一直在寻找类似的东西——我就是无法让它工作。从用户的角度来看,ChangePolXTo有点混乱(不过这里只是一个noob),但我肯定喜欢这种方法:)我会将
ChangePol1To
移动到
Config
内部
Config
的语法类似于
DefaultConfig::WithPol1::WithPol3
,看起来更清晰。顺便说一句,
使用MyConfig1=Config;使用MyConfig2=Config可能就足够了。@Jarod42“将它放在配置中”是个好主意,看起来好多了!关于你的第二个建议:当你有10个策略时,改变最后一个策略需要你先重复9个默认策略。我想避免这种情况,我说了“可能”,所以这取决于OP的用法。OP有多少种不同的配置,它们之间有多大的不同,它们是否以某种方式联系在一起。。。
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;
}