C++ 设置模板布尔参数从类构造函数参数

huangapple go评论74阅读模式
英文:

C++ Set Template Bool Parameter from Class Constructor Argument

问题

下面是翻译好的部分:

我已经在下面尽量简化了场景。想象一个具有使用布尔参数的模板特化的类。

template <bool hasExtraParam>
class TestClass {};

template <>
class TestClass<true> {
   public:
    int param1;
    int param2;
};

template <>
class TestClass<false> {
   public:
    int param1;
};

现在,我想要一个容器类,它作为成员变量持有大量这些 TestClass 实例。我希望能够基于构造函数参数设置每个成员变量的模板参数,如下所示:

constexpr bool ep1, ep2, ep3, ep4;
class Container {
   public:
    constexpr Container(bool extraParam1, bool extraParam2, bool extraParam3,
                        bool extraParam4) {
        ep1 = extraParam1;
        ep2 = extraParam2;
        ep3 = extraParam3;
        ep4 = extraParam4;
    }
    TestClass<ep1> testClass1;
    TestClass<ep2> testClass2;
    TestClass<ep3> testClass3;
    TestClass<ep4> testClass4;
};

我该如何实现这种模式?我想在实际用例中传递一个大型配置结构体,其中包含一个布尔值,该值将链接到每个成员变量,设置其相应的模板参数。我无法理解如何实现这一点,感觉自己可能错过了解决问题的某种基本方法。此外,出于可扩展性考虑,我不认为容器应该有大量的模板参数,因为配置结构体可能很大。

希望这对你有帮助。如果你有其他问题或需要进一步的帮助,请随时告诉我。

英文:

I've simplified the scenario as much as possible below. Imagine a class that has template specialization using a bool parameter.

template &lt;bool hasExtraParam&gt;
class TestClass {};

template &lt;&gt;
class TestClass&lt;true&gt; {
   public:
    int param1;
    int param2;
};

template &lt;&gt;
class TestClass&lt;false&gt; {
   public:
    int param1;
};

Now, I would like to have a container class that holds a large amount of these TestClasses as member variables. I want to be able to set the template parameter of each member variable based on the constructor arguments as below:

constexpr bool ep1, ep2, ep3, ep4;
class Container
{
   public:
    constexpr Container(bool extraParam1, bool extraParam2, bool extraParam3,
                        bool extraParam4)
    {
        ep1 = extraParam1;
        ep2 = extraParam2;
        ep3 = extraParam3;
        ep4 = extraParam4;
    }
    TestClass&lt;ep1&gt; testClass1;
    TestClass&lt;ep2&gt; testClass2;
    TestClass&lt;ep3&gt; testClass3;
    TestClass&lt;ep4&gt; testClass4;
};

How can I achieve this pattern? I want for my actual use-case to pass in a large config struct that has a boolean that will link to each member variable setting its respective template parameter. I cannot wrap my head around how to achieve this and feel like I'm missing some alternate fundamental approach to the problem. Also, I don't this its feasible for Container to have a bunch of templated arguments for scalability purposes since the config struct can be large.

答案1

得分: 1

你正在尝试的在C++中是不可能的。模板参数只能在编译时指定。相反,你将不得不在运行时动态实例化对象,例如:

class TestClassBase {
public:
    virtual ~TestClassBase() = default;

    // 两个类的共同成员...

    // 供两个类覆盖的虚拟方法...
};

template <bool hasExtraParam>
class TestClass {};

template <>
class TestClass<true> : public TestClassBase {
public:
    int param1;
    int param2;

    // 根据需要重写虚拟方法...
};

template <>
class TestClass<false> : public TestClassBase {
public:
    int param1;

    // 根据需要重写虚拟方法...
};

class Container
{
public:
    Container(bool extraParam1, bool extraParam2, bool extraParam3, bool extraParam4)
    {
        testClass1 = extraParam1 ? new TestClass<true> : new TestClass<false>;
        testClass2 = extraParam2 ? new TestClass<true> : new TestClass<false>;
        testClass3 = extraParam3 ? new TestClass<true> : new TestClass<false>;
        testClass4 = extraParam4 ? new TestClass<true> : new TestClass<false>;
    }

    ~Container()
    {
        delete testClass1;
        delete testClass2;
        delete testClass3;
        delete testClass4;
    }

    TestClassBase* testClass1;
    TestClassBase* testClass2;
    TestClassBase* testClass3;
    TestClassBase* testClass4;
};

或者:

template <bool hasExtraParam>
class TestClass {};

template <>
class TestClass<true> {
public:
    int param1;
    int param2;
};

template <>
class TestClass<false> {
public:
    int param1;
};

class Container
{
public:
    Container(bool extraParam1, bool extraParam2, bool extraParam3, bool extraParam4)
    {
        if (extraParam1)
            testClass1.emplace<TestClass<true>>();
        else
            testClass1.emplace<TestClass<false>>();

        if (extraParam2)
            testClass2.emplace<TestClass<true>>();
        else
            testClass2.emplace<TestClass<false>>();

        if (extraParam3)
            testClass3.emplace<TestClass<true>>();
        else
            testClass3.emplace<TestClass<false>>();

        if (extraParam4)
            testClass4.emplace<TestClass<true>>();
        else
            testClass4.emplace<TestClass<false>>();
    }

    std::variant<TestClass<true>, TestClass<false>> testClass1;
    std::variant<TestClass<true>, TestClass<false>> testClass2;
    std::variant<TestClass<true>, TestClass<false>> testClass3;
    std::variant<TestClass<true>, TestClass<false>> testClass4;
};
英文:

What you are attempting is not possible in C++. Template aarguments can only be specified at compile-time. You will have to instantiate the objects dynamically at runtime instead, eg:

class TestClassBase {
public:
    virtual ~TestClassBase() = default;

    // common members of both classes...

    // virtual methods for both classes to override...
};

template &lt;bool hasExtraParam&gt;
class TestClass {};

template &lt;&gt;
class TestClass&lt;true&gt; : public TestClassBase {
public:
    int param1;
    int param2;

    // override virtual methods as needed...
};

template &lt;&gt;
class TestClass&lt;false&gt; : public TestClassBase {
public:
    int param1;

    // override virtual methods as needed...
};

class Container
{
public:
    Container(bool extraParam1, bool extraParam2, bool extraParam3, bool extraParam4)
    {
        testClass1 = extraParam1 ? new TestClass&lt;true&gt; : new TestClass&lt;false&gt;;
        testClass2 = extraParam2 ? new TestClass&lt;true&gt; : new TestClass&lt;false&gt;;
        testClass3 = extraParam3 ? new TestClass&lt;true&gt; : new TestClass&lt;false&gt;;
        testClass4 = extraParam4 ? new TestClass&lt;true&gt; : new TestClass&lt;false&gt;;
    }

    ~Container()
    {
        delete testClass1;
        delete testClass2;
        delete testClass3;
        delete testClass4;
    }

    TestClassBase* testClass1;
    TestClassBase* testClass2;
    TestClassBase* testClass3;
    TestClassBase* testClass4;
};

Alternatively:

template &lt;bool hasExtraParam&gt;
class TestClass {};

template &lt;&gt;
class TestClass&lt;true&gt; {
public:
    int param1;
    int param2;
};

template &lt;&gt;
class TestClass&lt;false&gt; {
public:
    int param1;
};

class Container
{
public:
    Container(bool extraParam1, bool extraParam2, bool extraParam3, bool extraParam4)
    {
        if (extraParam1)
            testClass1.emplace&lt;TestClass&lt;true&gt;&gt;();
        else
            testClass1.emplace&lt;TestClass&lt;false&gt;&gt;();

        if (extraParam2)
            testClass2.emplace&lt;TestClass&lt;true&gt;&gt;();
        else
            testClass2.emplace&lt;TestClass&lt;false&gt;&gt;();

        if (extraParam3)
            testClass3.emplace&lt;TestClass&lt;true&gt;&gt;();
        else
            testClass3.emplace&lt;TestClass&lt;false&gt;&gt;();

        if (extraParam4)
            testClass4.emplace&lt;TestClass&lt;true&gt;&gt;();
        else
            testClass4.emplace&lt;TestClass&lt;false&gt;&gt;();
    }

    std::variant&lt;TestClass&lt;true&gt;, TestClass&lt;false&gt;&gt; testClass1;
    std::variant&lt;TestClass&lt;true&gt;, TestClass&lt;false&gt;&gt; testClass2;
    std::variant&lt;TestClass&lt;true&gt;, TestClass&lt;false&gt;&gt; testClass3;
    std::variant&lt;TestClass&lt;true&gt;, TestClass&lt;false&gt;&gt; testClass4;
};

huangapple
  • 本文由 发表于 2023年2月24日 08:14:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551553.html
  • c++
  • compilation
  • constexpr
  • template-specialization
  • templates
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定