我正在调试一个遍历可变参数模板参数并检查对(Type
,Tag
)的元函数,以查看每个Type
是否被相应的Tag
标记:
template<typename Type, typename Tag, typename ... Rest>
constexpr bool taggedTypes()
{
constexpr std::size_t restN = sizeof ...(Rest);
static_assert(restN % 2 == 0, "Odd number of (Type, Tag) pairs.");
constexpr bool pairDoesntMatch = ! taggedType<Type, Tag>();
if constexpr (pairDoesntMatch)
return false;
// Single pair, empty Rest, pair matches.
if (restN == 0)
return true;
// More than two pairs, test further.
if (restN > 2)
taggedTypes<Rest...>();
return true;
}
我的代码出了点问题,我想调试它。
如果我使用static_assert
输出restN
或任何其他constexpr
变量,我的程序将在编译时在断言时使用我指定的输出中断。另外,我还不清楚如何用static_assert()
写下字符串文字以外的任何内容。
如何使元程序遍历可变参数模板参数并输出调试所需的内容?
完整的示例:
#include <cassert>
#include <type_traits>
#include <cstddef>
struct fruit_tag {};
struct veggie_tag {};
template<typename T>
struct tag;
template<typename T, typename Tag>
constexpr
bool
taggedType()
{
constexpr bool sameTypes
= std::is_same<typename tag<T>::type, Tag>();
static_assert(sameTypes);
return sameTypes;
}
template<typename Type, typename Tag, typename ... Rest>
constexpr bool taggedTypes()
{
constexpr std::size_t restN = sizeof ...(Rest);
static_assert(restN % 2 == 0, "Odd number of (Type, Tag) pairs.");
constexpr bool pairDoesntMatch = ! taggedType<Type, Tag>();
if constexpr (pairDoesntMatch)
return false;
// Single pair, empty Rest, pair matches.
if (restN == 0)
return true;
// Many pairs, test further.
if (restN > 2)
taggedTypes<Rest...>();
return true;
}
class Orange {};
template<>
struct tag<Orange>
{
using type = fruit_tag;
};
class Apple {};
template<>
struct tag<Apple>
{
using type = fruit_tag;
};
class Turnip{};
template<>
struct tag<Turnip>
{
using type = veggie_tag;
};
int main()
{
static_assert(taggedTypes<Turnip, veggie_tag, Orange, fruit_tag>());
};
答案 0 :(得分:1)
As for displaying type at compile type for debugging, you might instantiate a non complete type using the value:
template <int> struct debug_int;
and then:
constexpr int magic = 42;
debug_int<magic>{}; // Compile error: invalid use of incomplete type 'struct debug_int<42>'
BTW, your taggedTypes
method can be simplified to:
template <typename Tuple, std::size_t ... Is>
constexpr bool taggedTypes(std::index_sequence<Is...>)
{
return (std::is_same<typename tag<std::tuple_element_t<2 * Is, Tuple>>::type,
std::tuple_element_t<2 * Is + 1, Tuple>>::value && ...);
}
template <typename ... Ts>
constexpr bool taggedTypes()
{
constexpr std::size_t size = sizeof ...(Ts);
//[[maybe_unused]]debug_odd<size> debug{};
static_assert(size % 2 == 0, "Odd number of (Type, Tag) pairs.");
return taggedTypes<std::tuple<Ts...>>(std::make_index_sequence<size / 2>{});
}
答案 1 :(得分:1)
This is probably more effort than you were hoping for, but there is also a patch that you can apply to GCC to enable a static_print
statement that does what you are looking for.
template<typename T, int s>
struct test
{
static_print("The template ", ::test, " has been instantiated as ", test, ". By the way, s + 1 is ", s + 1);
};
int main() {
test<int, 3> y;
return 0;
}
Compiling the above program prints out (at compile time):
The template test has been instantiated as test<int, 3>. By the way, s + 1 is 4
答案 2 :(得分:0)
我仔细研究了一下,发现了一个可能丑陋的解决方案,该解决方案不会停止编译并且不需要补丁。我正在使用一个引起编译器警告标记的元函数。例如,对于gcc,-Wbool-compare
可以这样使用,以输出编译时计算的结果:
template<int N>
constexpr bool warning_print()
{
return (0 < N < 100);
}
template<int N, int M>
constexpr void iterate()
{
warning_print<N>();
if constexpr (N + 1 < M)
iterate<N+1, M>();
return;
}
using namespace std;
int main()
{
iterate<5, 10>();
}
这给出了(在Linux上使用grep):
$ mainmake 2>&1 | grep -Ev 'recursive|required|comparisons like|(0 < N < 100)'
main.cpp: In function ‘constexpr bool warning_print()’:
main.cpp:4:19: warning: comparison of constant ‘100’ with boolean expression is always true [-Wbool-compare]
~~~~~~^~~~~
main.cpp: In instantiation of ‘constexpr bool warning_print() [with int N = 5]’:
~~^~~
main.cpp: In instantiation of ‘constexpr bool warning_print() [with int N = 6]’:
main.cpp: In instantiation of ‘constexpr bool warning_print() [with int N = 7]’:
main.cpp: In instantiation of ‘constexpr bool warning_print() [with int N = 8]’:
main.cpp: In instantiation of ‘constexpr bool warning_print() [with int N = 9]’: