簡體   English   中英

使用不完整(部分指定)模板化類型強制模板特化

[英]force template specialization with an incomplete (partially specified) templated type

當我嘗試使用不完整(部分指定)的模板化類型強制進行模板專業化時,我遇到了一些問題。

讓我們考慮這個過於簡單的示例:我有一個模板 function 聲明,我在相應的 C++ 文件中為某些常見類型提供了強制規范。

在.h文件中:

template <class T>
void doSomething(const T &value);

在.cpp文件中:

// force template specializations with various types
template <>
void doSomething<float>(const float &value)
{
  // actual code specialization for type float, es:
  printf("%.3f", value);
}
...

例如,我想對glm 向量(來自 OpenGL 數學庫)進行相同的專業化,它根據組件的數量和組件的數據類型(以及精度,我將在本例中跳過)進行模板化為清楚起見)。

我想避免的是為 N 的所有可能值顯式編寫實際特化(導致代碼重復,因為它基本上是相同的循環,但迭代次數不同),如下所示:

template <>
void doSomething<glm::vec<2, float>>(const glm::vec<2, float> &value)
{
  printf("{");
  printf("%.3f", value[0]);
  for (int i = 1; i< 2 ++i)
    printf(", %.3f", value[i]);
  printf("}");
}

template <>
void doSomething<glm::vec<3, float>>(const glm::vec<3, float> &value)
{
  printf("{");
  printf("%.3f", value[0]);
  for (int i = 1; i< 3 ++i)
    printf(", %.3f", value[i]);
  printf("}");
}

template <>
void doSomething<glm::vec<4, float>>(const glm::vec<4, float> &value)
{
  printf("{");
  printf("%.3f", value[0]);
  for (int i = 1; i< 4 ++i)
    printf(", %.3f", value[i]);
  printf("}");
}

我想做的是寫這樣的東西:

template <glm::length_t N>
void doSomething<glm::vec<N, float>>(const glm::vec<N, float> &value)
{
  printf("{");
  printf("%.3f", value[0]);
  for (int i = 1; i< N ++i)
    printf(", %.3f", value[i]);
  printf("}"); 
}
// force full template specializations
template void doSomething<glm::vec<2, float>>(const glm::vec<2, float> &value);
template void doSomething<glm::vec<3, float>>(const glm::vec<3, float> &value);
template void doSomething<glm::vec<4, float>>(const glm::vec<4, float> &value);

但此解決方案出現以下編譯錯誤:“非法使用顯式模板參數”

我讀到 C++ 不允許“功能部分專業化”,這個限制在現代標准 C++ (14/17/20) 中是否仍然有效? 這是問題的原因還是我遺漏了什么? 謝謝大家。

部分 Function 不允許特化。 但是,您可以通過使用 Function 重載來避免為 N 的所有可能值顯式編寫代碼。 下面的示例基於您的代碼,但我已將glm::vec<>替換為std::array<>因為它們相似。 另外,為了方便起見,我只使用了.C文件。

#include <cstdio>
#include <iostream>
#include <array>

using namespace std;

// Overload the function for various types
void doSomething(const float &value)
{
  // actual code for type float:
  printf("%.3f", value);
}

// overloading not specialization
template<std::size_t N>
void doSomething(array<float, N> &value)
{
    printf("{");
    printf("%.3f", value[0]);
    for (int i = 1; i < N; ++i)
        printf(", %.3f", value[i]);
    printf("}");
}

int main()
{
    float f = 5.0;
    doSomething(f);
    cout << endl;

    std::array<float, 3> a1 = {1, 2, 3};
    doSomething<3>(a1);
    cout << endl;

    std::array<float, 4> a2 = {1, 2, 3, 4};
    doSomething<4>(a2);
    cout << endl;
}

這是 output:

$ g++ --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
$ g++ -std=c++17 doSomething.C 
$ a.out
5.000
{1.000, 2.000, 3.000}
{1.000, 2.000, 3.000, 4.000} 
$

作為 Luis 的超載答案的替代方案,您還可以添加額外的抽象級別。 您可以編寫一個單獨的 function 來處理數組,然后從doSomething中調用它:

template<std::size_t N>
void doSomethingForArray(array<float, N> &value)
{
    printf("{");
    printf("%.3f", value[0]);
    for (int i = 1; i < N; ++i)
        printf(", %.3f", value[i]);
    printf("}");
}

template <>
void doSomething<glm::vec<2, float>>(const glm::vec<2, float> &value)
{ doSomethingForArray(value); }

template <>
void doSomething<glm::vec<3, float>>(const glm::vec<3, float> &value)
{ doSomethingForArray(value); }


template <>
void doSomething<glm::vec<4, float>>(const glm::vec<4, float> &value)
{ doSomethingForArray(value); }

鑒於您的原始解決方案仍然需要顯式實例化所有 3 個函數,我認為這不是很大的開銷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM