c++ - 有没有办法在编译时实例化所有 C++ 模板大小?

标签 c++ templates c++-cli

下面的 c++/cli 模板可以正常工作,但似乎应该有一种方法可以进一步概括模板或添加一个可以在编译时创建模板实例的助手。

我在想 http://en.cppreference.com/w/cpp/utility/integer_sequence可能有效,但需要帮助程序/实现程序功能的一些帮助。

简化 main 以演示所需语法与当前使用的语法:

int main(array<String^>^ args) {

    // the actual number of possible char lengths is sparse (generally)
    // but the API allows for 1-1024
    List<int>^ varList = gcnew List<int>();
    varList->Add(40);
    varList->Add(80);
    varList->Add(128);

    SortedList<int, List<String^>^>^ allStrings = gcnew SortedList<int, List<String^>^>();

    // want something like this, but the compiler complains that 
    // the template is invalid expectes compile-time constant expressions
    for each(int key in varList) {
        allStrings->Add(key, UpdateTest<key>());
    }

    // this works, but has 1024 lines of case N:
    for each(int key in varList) {
        switch (key) {
        case 1: allStrings->Add(key, UpdateTest<1>());
        case 2: allStrings->Add(key, UpdateTest<2>());
        case 3: allStrings->Add(key, UpdateTest<3>());
            //... all 1024 possible char[N] sizes...
        case 1024: allStrings->Add(key, UpdateTest<1024>());
        }
    }
}

模板适用于 1024 switch case N: 调用。有没有办法让助手/实现者在没有案例的情况下实例化所有 1024?

template <std::size_t N> List<String^>^ APIwrapper::UpdateTest() {
    typedef char CHARX[N];  // N valid for 1 to 1024
    CHARX vals[MAXFIELDS];

    // NATIVE C++ VendorAPI(short, void*) vals is the address of the word aligned destination data
    int count = VendorAPI(N, &vals); 

    List<String^>^ retList = gcnew List<String^>();

    for (int c = 0; c < count; c++) {
        CHARX temp;
        strncpy(temp, vals[c], N);  // \0 terminated char arrays
        String^ x = gcnew String(temp);
        retList->Add(x->Substring(0, N)->Trim());
    }
    return retList;
}

最佳答案

以下答案适用于 c++14,我不知道它是否与 cli 兼容。

您可以使用模板生成函数指针的 std::array:

using UpdateTestPtr = decltype(&UpdateTest<0>);

// Struct used to generate the array's content.
template<typename Sequence>
struct UpdateTestArrayImpl;

// Specialization used to get the values in the integer sequence.
template<std::size_t... indices>
struct UpdateTestArrayImpl<std::integer_sequence<std::size_t,indices...>> {
    static constexpr std::array<UpdateTestPtr,sizeof...(indices)> value{UpdateTest<indices>...};
};

// Factorise sequence creation
template<std::size_t N>
using UpdateTestArray = UpdateTestArrayImpl<std::make_index_sequence<N>>;

static constexpr std::size_t N = 512;
// The array is needed at runtime. Create a normal (not constexpr) instance.
static std::array<UpdateTestPtr,N> functionArray = UpdateTestArray<N>::value;

并将 switch/case 转换为数组查找:

for each(int key in varList) {
    allStrings->Add(key, functionArray[key]());
}

Live demo

一些编译器可能会产生“模板实例化深度”错误,这取决于 make_integer_sequence 的实现方式。递归深度的最大限制通常可以通过编译器选项增加。

关于c++ - 有没有办法在编译时实例化所有 C++ 模板大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46865317/

相关文章:

.net - 无法加载文件或程序集系统找不到指定的文件

c# - 为什么有些人将大括号放在与语句相同的行,而另一些人则另起一行?

c++ - 使用模板减少 const 和非 const 非成员函数的代码重复

c++ - xlc: 模板类的 sizeof 不工作

指针成员的 c++/CLI 包装器 - c++ 单例实例

winforms - 对象定义中的 ^ 是什么?

c++ - 为什么我的类(class)没有链接?

c++ - 在 ios/xcode 中执行 c 断言后如何跳过或继续?

C++ 二维数组到一维数组

templates - 如何在 D 编程语言中创建 DLLAPI() 模板混合,其行为类似于 C/C++ 中众所周知的 DLLAPI(或类似)宏?