SomeClass我有一個看起來像這樣的可變引數模板類(基本上):
template<std::size_t SIZE_>
class SomeClass {
public:
static constexpr std::size_t SIZE = SIZE_;
};
它有一個 constexpr 成員,它只包含std::size_t用于實體化它的模板引數。我想要一個constexpr可以總結所有SomeClass<SIZE_>專業化大小的函式。我的第一個想法是制作一個簡單的可變引數模板函式,它可以SIZE像這樣添加所有 s:
template<typename T>
constexpr std::size_t totalSize() {
return T::SIZE;
}
template <typename T, typename... Ts>
constexpr std::size_t totalSize() {
return totalSize<T>() totalSize<Ts...>();
}
現在我嘗試呼叫它:
constexpr std::size_t size = totalSize<SomeClass<1>, SomeClass<2>, SomeClass<3>>() // should return 6
事實證明,最后一個引數解包使得對totalSize<T>函式的呼叫不明確,因為兩個模板totalSize函式都匹配它。好吧,我修改了我的代碼以具有兩個不同的功能并提出了這個:
template<typename T>
constexpr std::size_t totalSizeSingle() {
return T::SIZE;
}
template <typename T, typename... Ts>
constexpr std::size_t totalSize() {
std::size_t result = totalSizeSingle<T>();
if (sizeof...(Ts) > 0) result = totalSize<Ts...>();
return result;
}
同樣,最后一次拆包似乎有問題。顯然,T即使在編譯時已知,也無法推斷。我收到以下錯誤(使用 GCC 編譯):
In instantiation of 'constexpr std::size_t totalSize() [with T = SomeClass<3>; Ts = {}; std::size_t = long long unsigned int]':
main.cpp:129:51: required from here
main.cpp:134:82: in 'constexpr' expansion of 'totalSize<SomeClass<1>, SomeClass<2>, SomeClass<3> >()'
main.cpp:129:51: in 'constexpr' expansion of 'totalSize<SomeClass<2>, SomeClass<3> >()'
main.cpp:129:58: error: no matching function for call to 'totalSize<>()'
129 | if (sizeof...(Ts) > 0) result = totalSize<Ts...>();
| ~~~~~~~~~~~~~~~~^~
main.cpp:127:23: note: candidate: 'template<class T, class ... Ts> constexpr std::size_t totalSize()'
127 | constexpr std::size_t totalSize() {
| ^~~~~~~~~
main.cpp:127:23: note: template argument deduction/substitution failed:
main.cpp:129:58: note: couldn't deduce template parameter 'T'
129 | if (sizeof...(Ts) > 0) result = totalSize<Ts...>();
| ~~~~~~~~~~~~~~~~^~
我真的不明白為什么它不起作用。每種型別在編譯時都是已知的。為什么會發生這種情況,我怎樣才能讓它作業?我正在使用 C 11。
uj5u.com熱心網友回復:
人們在 C 模板元編程中呼叫structs元函式是有原因的。
在我們的例子中,在結構中進行元編程的主要優點是通過模板引數解決函式多載與類專業化不同且更受限制。
所以我建議:
template <class ...> // only called if there's no arguments
struct add_sizes {
static constexpr auto value = 0;
};
template <class T, class ... Ts>
struct add_sizes <T, Ts...> {
static constexpr auto value = T::SIZE add_sizes<Ts...>::value;
};
// then wrap it into your function:
template <class ... Ts>
constexpr std::size_t totalSize () {
return add_sizes<Ts...>::value;
}
演示
使用結構的另一個優點是可以輕松“回傳”多個值或型別,這對于函式來說變得復雜。有時通過計算A你已經計算了B,所以存盤兩者是有意義的。
一般來說,我會說,如果你一直在努力解決函式的元編程問題,請切換到結構。
uj5u.com熱心網友回復:
問題是當模板引數串列的大小為 1 時totalSize<Ts...>();會呼叫totalSize<>()但totalSize<>();未定義。
您可以通過將第一個版本設為 2 或制作模板引數來使其正常作業。
template<typename T>
constexpr std::size_t totalSize() {
return T::SIZE;
}
template <typename T, typename U, typename... Ts>
constexpr std::size_t totalSize() {
return totalSize<T>() totalSize<U, Ts...>();
}
演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/488659.html
上一篇:矩陣類突然結束的C 程式
