我有以下代碼遍歷 a 的型別std::tuple并將它們的名稱連接為字串。
#include <type_traits>
#include <tuple>
#include <string>
template<typename types_T, int n, typename T>
concept tuple_element_is = (std::is_same<typename std::tuple_element<n, types_T>::type, T>::value);
template<typename types_T, int n>
requires tuple_element_is<types_T, n, float>
constexpr const std::string foo() {
if constexpr (n < std::tuple_size<types_T>::value - 1) {
return "float" foo<types_T, n 1>();
} else {
return "float";
}
}
template<typename types_T, int n>
requires tuple_element_is<types_T, n, int>
constexpr const std::string foo() {
if constexpr (n < std::tuple_size<types_T>::value - 1) {
return "int" foo<types_T, n 1>();
} else {
return "int";
}
}
auto t0 = foo<std::tuple<int>, 0>();
auto t1 = foo<std::tuple<float>, 0>();
auto t2 = foo<std::tuple<int, int>, 0>();
auto t3 = foo<std::tuple<int, float>, 0>();
//auto t4 = foo<std::tuple<float, int>, 0>(); -- does not compile
auto t5 = foo<std::tuple<float, float>, 0>();
auto t6 = foo<std::tuple<int, int, int>, 0>();
auto t7 = foo<std::tuple<int, int, float>, 0>();
//auto t8 = foo<std::tuple<int, float, int>, 0>(); -- does not compile
auto t9 = foo<std::tuple<int, float, float>, 0>();
//auto t10 = foo<std::tuple<float, int, int>, 0>(); -- does not compile
//auto t11 = foo<std::tuple<float, int, float>, 0>(); -- does not compile
//auto t12 = foo<std::tuple<float, float, int>, 0>(); -- does not compile
auto t13 = foo<std::tuple<float, float, float>, 0>();
實體化t4, t8, t10, t11, t12不編譯并產生此錯誤:
note: template argument deduction/substitution failed:
note: constraints not satisfied
In substitution of ‘template<class types_T, int n> requires tuple_element_is<types_T, n, float> constexpr const string foo() [with types_T = std::tuple<float, int>; int n = 1]’:
required from ‘constexpr const string foo() [with types_T = std::tuple<float, int>; int n = 0; std::string = std::__cxx11::basic_string<char>]’
required from here
required for the satisfaction of ‘tuple_element_is<types_T, n, float>’ [with types_T = std::tuple<float, int>; n = 1]
note: the expression ‘std::is_same<typename std::tuple_element<(long unsigned int)n, types_T>::type, T>::value [with n = 1; types_T = std::tuple<float, int>; T = float]’ evaluated to ‘false’
最后一個note很有趣,因為這個運算式的計算結果確實是false,但他在第二次呼叫中使用了 float 變體。也許我用錯了,但編譯器應該重新檢查每個遞回呼叫的要求foo并選擇正確的替換,在這種情況下int。更有趣的是,它的作業方式與t3, t7
注意相反,foo<std::tuple<float, int>, 1>();直接呼叫也可以。
我已經用 GCC 和 clang 對其進行了測驗,它們產生了相同的結果。
任何想法?
uj5u.com熱心網友回復:
Clang 給了我一個非常直接的錯誤資訊:
error: call to function 'foo' that is neither visible in the template definition nor found by argument-dependent lookup
return "float" foo<types_T, n 1>();
^
note: in instantiation of function template specialization 'foo<std::tuple<float, int>, 0>' requested here
auto t4 = foo<std::tuple<float, int>, 0>(); //-- does not compile
^
note: 'foo' should be declared prior to the call site
constexpr const std::string foo() {
的int變體foo在變體中不可見float,并且“應該在呼叫站點之前宣告”。換句話說,它應該是前向宣告的,像這樣:
template<typename types_T, int n>
requires tuple_element_is<types_T, n, int>
constexpr const std::string foo();
演示
GCC 的錯誤資訊有點難以理解,但是當你習慣于模板相關的錯誤資訊時,它仍然相對簡單:
error: no matching function for call to 'foo<std::tuple<float, int>, (0 1)>()'
12 | return "float" foo<types_T, n 1>();
| ~~~~~~~~~~~~~~~~~~~^~
note: candidate: 'template<class types_T, int n> requires tuple_element_is<types_T, n, float> constexpr const std::string foo()'
10 | constexpr const std::string foo() {
它沒有提到任何其他候選人,這意味著它只考慮它可以看到的那個:第一個。再次,因為第二個沒有在那個時候宣告。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/518281.html
標籤:C 模板c -概念
上一篇:模板類錯誤中的顯式特化
