Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在宏之外的代码中有选择地编译_C++_Unit Testing_Debugging_Templates_Metaprogramming - Fatal编程技术网

C++ 在宏之外的代码中有选择地编译

C++ 在宏之外的代码中有选择地编译,c++,unit-testing,debugging,templates,metaprogramming,C++,Unit Testing,Debugging,Templates,Metaprogramming,是否可以使用模板在代码的某些部分选择性地编译,或者这仅限于预处理器?例如,如果我想用预处理器删除一段代码,我知道我可以: #if 0 static const char[] hello_world = "hello, world"; #endif 是否还有其他方法可以对模板执行相同的操作 万一我问错了问题,下面是我要做的。我想在启动应用程序时加载一些代码。通常,我只需要使用构造函数来做我想做的事情,并创建一个静态变量。但是我希望这只发生在调试版本中,并且代码不会在发布版本中运行。我正在使用的代

是否可以使用模板在代码的某些部分选择性地编译,或者这仅限于预处理器?例如,如果我想用预处理器删除一段代码,我知道我可以:

#if 0
static const char[] hello_world = "hello, world";
#endif
是否还有其他方法可以对模板执行相同的操作

万一我问错了问题,下面是我要做的。我想在启动应用程序时加载一些代码。通常,我只需要使用构造函数来做我想做的事情,并创建一个静态变量。但是我希望这只发生在调试版本中,并且代码不会在发布版本中运行。我正在使用的代码是使用宏创建的,因此我似乎无法将“#if 0”放入宏中并使其正确展开

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()
我喜欢它的语法外观,但我看不到使用宏摆脱函数体的方法。我尝试改用begin/end宏,结果得到:

#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
这似乎不起作用

编辑2:原来的问题与原来的问题大不相同。更改名称,希望它更符合实际问题。

传统上,“调试”代码将被包装在这样的块中,使用预处理器而不是编译器:

#ifdef DEBUG
// Some debugging code here...
#endif
…并将
-DDEBUG
传递到预处理器中,仅用于“调试”生成

但是,最好解决“调试”和“发布”构建之间的差异。调试块通常是未解决问题的指示器


我建议您完全删除这些条件。

您可以使用类似Boost中的条件元函数之类的东西

boost::mpl::if_c <debug, MyDebuggingClass, EmptyClass>::type MyObject;
boost::mpl::if_c::type MyObject;

这将根据常量表达式的值选择变量
MyObject
debug

,您需要预处理器条件来摆脱声明。但是,如果只想在函数中间启用/禁用块,那就没问题。您可以使用模板专门化,但最简单的事情就是使用
如果(_DEBUG){…}
,在发布版本中编译器将优化掉死代码。

考虑到您的编辑,似乎您正在使这变得比必须的困难得多。在定义宏的地方,提供一个
#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
最后一个选项是使用中间宏有选择地声明静态选项本身[对于这个宏的语法不是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()

在任何情况下,函数体都会存在,但由于您从未调用过它,因此这并不重要。

函数体的可能重复就是重复,但遗憾的是,似乎没有解决方案:(不清楚您想要启用或禁用什么。您展示了一个全局变量的示例,但您的描述涉及到启用或禁用代码。而且还涉及到一些宏。您能否提供一个“如果0
在宏中,则无法将
#您遇到的问题?您可以使用的另一个问题是
enable\u if
:原因是我希望它用于单元测试库,其中测试嵌入到主函数之前运行,但会在发布构建期间删除(以免影响性能或崩溃)。类似于D处理单元测试的方式。因此,这不是关于未解决的问题,但使其如此运行程序与运行单元测试并选择性地禁用它是一样的。@Jonathan Sternberg:这使它成为一个更有趣的问题:)这似乎可行。带有-O2的g++从生成的可执行文件中去掉未使用的符号。使用默认的g++参数(无优化)保留未使用的符号,并生成更大的可执行文件。我还意识到这会导致在g++上使用-Wall抛出警告。所以,虽然它有效,但如果有人使用-墙,那就不好了。@乔纳森:警告是什么?
int main() {
    #ifndef NDEBUG
    unit_tests::run_all_tests(); //or whatever
    #endif
    //regular old code
}
#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()