如何使用静态数组元素作为不同模板实例化对象的静态数组的索引

How do I use a static array element as an index to a static array of objects that are of different template instantiations

本文关键字:静态 实例化 对象 数组 索引 数组元素 何使用      更新时间:2023-10-16

如何使用静态数组元素作为不同模板实例化对象的静态数组的索引?

我卡住了明显的编译器错误:无效的模板参数为'N',预期的编译时常量表达式。

我不知道是否有一个非c++11的答案。希望有一些现代的东西,我可以在vs2013中使用…:)

我试图静态地存储数据,像这样:

static const char* size1Array[1] =
{
    "hello"
};
static const char* size2Array[2] =
{
    "foo",
    "bar"
};
static const size_t ARRAYSIZES[2] =
{
    1,
    2
};
// Empty parent
struct DataParent {};
template <size_t N>
struct DataChild : DataParent
{
    DataChild(const char*(*arrIn)[N])
        : arr(arrIn) {}
    const char*(*arr)[N];
};
// The arrays are of different sizes, hence the DataParent to keep them in a static array
static DataParent DataTable[ 2 ] =
{
    DataChild< 1 >(&size1Array),
    DataChild< 2 >(&size2Array)            
};
int main()
{
    int index = 1;
    // The tricky cast that won't compile (ARRAYSIZES[index] 
    std::cout << ((DataChild< ARRAYSIZES[index] >*)&DataTable[index])->arr[0] << std::endl;
}

我想访问静态数组中的对象,但我不能使用非编译常数。我正在运行VS2013 Update 4.

你有几个问题:

  • 切片问题,当你存储数据为值

static DataParent DataTable[2] =
{
    DataChild<1>(&size1Array), // Slicing
    DataChild<2>(&size2Array)  // Slicing
};

应该是这样的:

static DataChild<1> child1(&size1Array);
static DataChild<2> child2(&size2Array);
static DataParent* DataTable[2] = {&child1, &child2};

,所以你的cast不再是UB。

  • 和编译时间问题:

    const size_t ARRAYSIZES[2] = { 1, 2 };
    int index = 1;
    
    下面的

    不是编译时常数:

    ARRAYSIZES[index] // Not a compile time value.
    

出于某种原因,在下一行使用constexpr而不是const对我来说是有效的。我还不知道为什么。请看我问的关于这个主题的问题。

// static const size_t ARRAYSIZES[2] =   // Does not work
static constexpr size_t ARRAYSIZES[2] =  // Works
{
    1,
    2
};

下面的语句将创建两个子对象,但只存储父对象,父对象为空。我不知道那对你有什么帮助。

static DataParent DataTable[ 2 ] =
{
    DataChild< 1 >(&size1Array),
    DataChild< 2 >(&size2Array)            
};

也许你需要指针。

static DataParent* DataTable[ 2 ] =
{
    new DataChild< 1 >(&size1Array),
    new DataChild< 2 >(&size2Array)            
};

或智能指针

static std::unique_ptr<DataParent> DataTable[ 2 ] =
{
    new DataChild< 1 >(&size1Array),
    new DataChild< 2 >(&size2Array)            
};

在阅读了更多关于constexpr的内容后,我明白了为什么

static constexpr size_t ARRAYSIZES[2] =  { ... };

工作,但

static const size_t ARRAYSIZES[2] =  { ... };

不工作

constexpr需要在编译时可求值,而const则不需要。

给定

double read_double()
{
   double v;
   std::cin >> v;
   return v;
}
const double v1 = read_double();

就可以了。v1在运行时初始化。初始化后,它保持不变。

constexpr double v2 = read_double();

不行,因为read_double()不是constexpr,不能在编译时求值。因此,它不能用于在编译时初始化v1