是否可以在编译时输出 constexpr 变量来调试模板元程序
Is it possible to output constexpr variables at compile time to debug template metaprograms?
我正在调试一个元函数,该函数迭代可变参数并检查对(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>());
};
至于在编译类型处显示类型以进行调试,您可以使用以下值实例化非完整类型:
template <int> struct debug_int;
然后:
constexpr int magic = 42;
debug_int<magic>{}; // Compile error: invalid use of incomplete type 'struct debug_int<42>'
简单演示
演示您的案例
顺便说一句,您的taggedTypes
方法可以简化为:
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>{});
}
演示
这可能比您希望的要多,但是您还可以将一个补丁应用于GCC,以启用执行您正在寻找的static_print
语句。
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;
}
编译上述程序打印出来(在编译时):
The template test has been instantiated as test<int, 3>. By the way, s + 1 is 4
我挖了
一下,发现了一个可能很丑陋的解决方案,它不会停止编译,也不需要补丁。我正在使用一个元函数,它会导致编译器警告标记。例如,对于 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]’:
相关文章:
- 如何在添加文件的情况下在VSCode中调试C++程序
- 如何在 VsCode 上调试 C++/C 程序
- 调试C++程序时遇到问题
- 如何模拟时间的流逝来调试程序?
- 如何在main()之前调试程序崩溃
- 当Visual Studio停止调试程序时会自动清理内存
- VS 代码C++:无法启动调试 - 程序路径丢失或无效
- 如何在 arm 平台中调试 c 程序中的全局变量损坏
- 如何调试 C++ 程序
- 如何使用数组调试C++程序
- 使用Valgrind调试程序-检测分段故障
- 调试程序时奇怪的GDB消息C++
- 使用gdb在MS VC++2010 Express中编译的调试程序
- 调试C程序的断言错误
- CRT参数验证使多线程调试程序崩溃
- 在Linux下捕获SIGKILL的调试程序
- 在c++中调试程序时,我得到一个空白屏幕
- 在GDB中调试程序时如何获取程序的环境
- 尝试调试c++程序在Eclipse Mars上的MAC Pro视网膜与OS X Yosemite版本10.10.5
- 使用容器调试 C++ 程序<set>