代碼中的主要問題不是終止模板遞歸,而是array + 1
不是有效的模板非類型參數,如標準中[14.3.2]中所述。對於C++ 11和14,這樣的說法必須具有特定的形式,&
ID-表達,可能省略&
。在C++ 14之後,需求已經被放寬並且以常量表達式的更新規則來表示,但是仍然參數不能是子對象的地址;這排除了任何指針算術,因爲它是根據子對象的地址定義的。
如果你堅持使用基於類模板(不是我的第一選擇,見下文)的解決方案,可以解決通過避免模板參數指針運算;這裏有一個辦法做到這一點,包括檢查結束模板遞歸:
#include <iostream>
#include <cstddef>
template<const char* P, std::size_t I = 0, char = P[I]> struct len
{
static constexpr std::size_t value = len<P, I + 1>::value + 1;
};
template<const char* P, std::size_t I> struct len<P, I, 0>
{
static constexpr std::size_t value = 0;
};
constexpr char a[] = "this is a test";
int main()
{
constexpr auto s = len<a>::value;
std::cout << s << '\n';
}
爲清楚起見,我用char
的元素類型,因爲這是你在找什麼,據我瞭解。該解決方案顯然可以擴展到可以是非類型模板參數類型的任何T
。對於不能直接傳遞的T
,最後一個模板參數可以是bool
,它接收調用確定結束條件的constexpr
謂詞的結果。
然而,一個更簡單,更清晰的解決方案涉及基本實現在constexpr
功能strlen
;只要它是一個常量表達式,即使在C++ 11中,也可以使用這樣的調用表達式作爲模板參數。對於C++ 14,它是如此簡單:
#include <iostream>
#include <cstddef>
constexpr std::size_t const_len(const char* p)
{
std::size_t i = 0;
while(p[i] != 0) ++i;
return i;
}
extern constexpr char a[] = "this is a test";
int main()
{
constexpr auto s = const_len(a);
std::cout << s << '\n';
}
與C++ 11條constexpr
遵守規則遞歸溶液同樣很簡單。
如何使用'std :: array'? –
@πάνταῥεῖ我不能這樣做,因爲我不希望在字符串長度類型(即有違有一個神奇的模板獲取字符串的長度的點,所以我沒有這樣做) – DarthRubik
這有更高的目的嗎?你不能只使用sizeof(數組)? – md5i