[英]force template specialization with an incomplete (partially specified) templated type
當我嘗試使用不完整(部分指定)的模板化類型強制進行模板專業化時,我遇到了一些問題。
讓我們考慮這個過於簡單的示例:我有一個模板 function 聲明,我在相應的 C++ 文件中為某些常見類型提供了強制規范。
template <class T>
void doSomething(const T &value);
// 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.