在宏之外的代码中进行选择性编译
Selectively compiling in code outside of a macro
是否可以使用模板选择性地编译代码的某些部分,或者仅限于预处理器?例如,如果我想用预处理器删除一段代码,我知道我可以做到:
#if 0
static const char[] hello_world = "hello, world";
#endif
有没有对模板做同样的事情?
万一我问错了问题,下面是我要做的。我想在启动应用程序时加载一些代码。通常,我只需要使用构造函数来执行我想要的任何操作,并创建一个静态变量。但我希望这只发生在调试构建中,并且代码在发布构建期间不运行。我正在使用的代码是用宏创建的,所以我似乎无法将"#if0"放入宏中并使其正确展开。
在C++中有这样的方法吗?
编辑:这是我目前使用的宏代码的一个例子。
#define unittest(NAME)
struct unittest_ ## NAME :
public unittest::unittest_template<unittest_ ## NAME>
{
unittest_ ## NAME() :
unittest::unittest_template<unittest_ ## NAME>(#NAME) {}
void run_test();
};
static unittest_ ## NAME NAME ## _unittest;
void unittest_ ## NAME::run_test()
代码是通过以下操作使用的:
unittest(addTest)
{
assert_(5, 5); // there's an assert statement in the code
}
我喜欢它的语法,但我看不出有什么方法可以使用宏来摆脱函数的主体。我尝试使用开始/结束宏,结果得到:
#ifdef UNITTEST
# define unittest_begin(NAME) // previous code
# define unittest_end() // nothing needed
#else
# define unittest_begin(NAME) #if 0
# define unittest_end() #endif
#endif
这似乎不起作用。
第二版:原来的问题和原来的完全不同。更改名称,希望它与实际问题更相关。
您需要预处理器条件来消除声明。但如果你只想在函数中间启用/禁用一个块,那没问题。您可以使用模板专门化,但最简单的事情就是使用if (_DEBUG) { ... }
,在发布版本中,编译器会优化掉死代码。
传统上,"调试"代码会被包装在这样的块中,使用预处理器而不是编译器:
#ifdef DEBUG
// Some debugging code here...
#endif
并且将-DDEBUG
传递到预处理器中仅用于"调试"构建。
然而,最好解决"调试"answers"发布"构建之间的差异。调试块通常是未解决问题的指示器。
我的建议是你完全取消这些条件。
考虑到您的编辑,这似乎比必须的要困难得多。在定义宏的地方,提供一个#ifdef
块,并选择如何定义它。
#ifdef NDEBUG
#define unittest(NAME) static void dummy_func_##NAME()
#else
#define unittest(NAME)
struct unittest_ ## NAME :
public unittest::unittest_template<unittest_ ## NAME>
{ unittest_ ## NAME() :
unittest::unittest_template<unittest_ ## NAME>(#NAME) {}
void run_test();
};
static unittest_ ## NAME NAME ## _unittest;
void unittest_ ## NAME::run_test()
#endif
您也可以在那里使用单个定义,并将main
更改为
int main() {
#ifndef NDEBUG
unit_tests::run_all_tests(); //or whatever
#endif
//regular old code
}
最后一个选项是使用中间宏选择性地声明静态选项本身[不能100%确定这个选项的语法]
#ifndef NDEBUG
#define DECLARE(NAME) static unittest_##NAME NAME##_unittest;
#else
#define DECLARE(NAME) /* noop */
#endif
#define unittest(NAME)
struct unittest_##NAME { /*add internals*/ };
DECLARE(NAME);
void unittest_##NAME::run_test()
在所有情况下,函数的主体仍然存在,但由于您从未调用过它,所以这并不重要。
您可以使用Boost中的条件元函数。
boost::mpl::if_c <debug, MyDebuggingClass, EmptyClass>::type MyObject;
这基于常量表达式debug
的值来选择变量MyObject
的类型。
- 从命令行c++发送文本文件名
- 使用新行和不使用新行读取文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 预处理器:插入结构名称中的前一个行号
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 使用一个考虑到std::map中键值的滚动或换行的键
- MSVC多行宏编译器错误
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 计算所选行的总和
- 如何从 gtkmm 树视图中获取所选行
- 如何在多行文本C++的左上角显示复选框
- 如何将所选行的第一列值绑定到变量并在 QT 的 SQL 命令中使用它?
- 如何让我的QTableView与QSqlTableModel具有复选框和多行?
- 是否有一个WinAPI可以从带有可选空格和其他参数的命令行获取文件名
- TCLAP:如何检查是否指定了可选的命令行参数
- 可选的命令行参数
- Qt C++ 从 QTableView 中获取所选行的每个单元格的数据
- 当输入行结尾混合时,Std::getline可选
- C++ 中客户端程序的可选命令行参数
- QTableView的选定项中所选行/行的顺序