派生类中的 constexpr 可以在不实例化任何类的情况下初始化基类成员吗?

问题描述 投票:0回答:1

我有一些通用功能,我只想在基类中实现一次。我有许多(许多!)不同的案例,它们具有相同的结构,但应应用此功能的数据不同。每个派生类都实现自己的数据集。这些派生类将由一些外部代码自动生成。

请参阅下面的可编译和可运行的示例。目前我可以在实例化相应的派生类后调用下面的

getData()
方法。

#include<array>
#include <iostream>

struct myStruct
{
    int id;
    int size;
};

class myBase
{
protected:
    const myStruct *myStructArray;

    myBase(const myStruct *structArray)
    {
        myStructArray = structArray;
    };

public:
    // This functionality is in my real case much more complex.
    // I want to define this functionality only once, and not repeatetly in the derived classes as it will become unmainainable.
    // But since all information is known at compile time and const, I want to be able to access this method staticially as:
    // `myDerived1::getData(1);`, thus without having to instantiate the 'myDerived1' class.
    myStruct getData(int index)
    {
        return *(myStructArray + index);
    }
};

// An example of a derived class defining the data.
class myDerived1 : public myBase
{
    constexpr static auto carrFieldMetaData{
        []() { // A lambda function that initializes the array as a constexpr where the array indexes are explicitly denoted.
            std::array<myStruct, 2> myStructData{};
            myStructData[0] = {.id = 0, .size = 1};
            myStructData[1] = {.id = 1, .size = 2};
            return myStructData;
        }()};

public:
    myDerived1() : myBase(carrFieldMetaData.data()){};
};

// Another example of the derived class with the same structure but different data.
class myDerived2 : public myBase
{
    constexpr static auto carrFieldMetaData{
        []() { // A lambda function that initializes the array as a constexpr where the array indexes are explicitly denoted.
            std::array<myStruct, 3> myStructData{};
            myStructData[0] = {.id = 0, .size = 8};
            myStructData[1] = {.id = 1, .size = 9};
            myStructData[2] = {.id = 2, .size = 1};
            return myStructData;
        }()};

public:
    myDerived2() : myBase(carrFieldMetaData.data()){};
};

int main(int argc, char** argv) {
    myBase test = myDerived1();
    std::cout << test.getData(0).size << '\n';
    std::cout << test.getData(1).size << '\n';
};

我尝试进行数据定义

constexpr
,因为所有信息在编译时都是已知的。所以我想我不需要任何类的实例,但是
getData()
类中的
myBase
方法必须是静态的,例如:

static myStruct getData(int index)
{
    return *(myStructArray + index);
}

然后像

myDerived1::getData(1);
那样调用它,而不必创建
getData
的实例。

我无法让它发挥作用。如果我认为我应该摆脱构造函数,因为它们只会在实例化我想要避免的类时被调用。那么如何初始化基类中的成员变量

myStructArray
呢?

这可能吗?如果有人可以将我的示例修改为固定的工作示例,这将是最有用的!


诗。我仍在学习 C++,所以如果我使用例如,请原谅我有些术语错误。

c++ inheritance static c++17 constexpr
1个回答
0
投票

@Jarod42 为我提供了一个很好的解决方案。

他创建了一个奇怪的重复模板模式(CRTP)。由于这种模式,基类可以直接访问派生类中的成员。

这使得我的示例中的基类成员过时,因此也消除了派生类实例化任何基类成员的需要。

这是一个非常优雅的解决方案,显然比我在问题中探索的方法更好。

工作示例如下:

#include<array>
#include <iostream>

struct myStruct
{
    int id;
    int size;
};

template <typename Derived>
class myBase
{
public:
    // This functionality is in my real case much more complex.
    // I want to define this functionality only once, and not repeatetly in the derived classes as it will become unmainainable.
    // But since all information is known at compile time and const, I want to be able to access this method staticially as:
    // `myDerived1::getData(1);`, thus without having to instantiate the 'myDerived1' class.
    constexpr static myStruct getData(int index)
    {
        return Derived::myStructArray[index];
    }
};

// An example of a derived class defining the data.
class myDerived1 : public myBase<myDerived1>
{
public:
    constexpr static auto myStructArray{
        []() { // A lambda function that initializes the array as a constexpr where the array indexes are explicitly denoted.
            std::array<myStruct, 2> myStructData{};
            myStructData[0] = {.id = 0, .size = 1};
            myStructData[1] = {.id = 1, .size = 2};
            return myStructData;
        }()};
};

// Another example of the derived class with the same structure but different data.
class myDerived2 : public myBase<myDerived2>
{
public:
    constexpr static auto myStructArray{
        []() { // A lambda function that initializes the array as a constexpr where the array indexes are explicitly denoted.
            std::array<myStruct, 3> myStructData{};
            myStructData[0] = {.id = 0, .size = 8};
            myStructData[1] = {.id = 1, .size = 9};
            myStructData[2] = {.id = 2, .size = 1};
            return myStructData;
        }()};
};

int main() {
    // Like before, working with an instance still works.
    auto test = myDerived1();
    std::cout << test.getData(0).size << '\n';
    std::cout << test.getData(1).size << '\n';

    // But now, it also works without an instance.
    std::cout << myDerived1::getData(0).size << '\n';
    std::cout << myDerived1::getData(1).size << '\n';

    std::cout << myDerived2::getData(0).size << '\n';
    std::cout << myDerived2::getData(1).size << '\n';
};
© www.soinside.com 2019 - 2024. All rights reserved.