лучше утверждать замену макроса в с ++ 17 - PullRequest
0 голосов
/ 03 июля 2019

Чтобы получить больше информации, чем традиционный макрос assert в c, я реализовал свой собственный макрос better_assert, предоставив возможность печатать дополнительную отладочную информацию.

Таким образом, можно заменить

assert( a == b );

на

better_assert( a == b, "Error: expect a == b, but a = ", a, " and b = ", b );

Код реализации выглядит так:

constexpr int debug_mode = 1;

namespace xxxxxxxx
{   // for macro `better_assert`
    template< typename... Args >
    void print_assertion(std::ostream& out, Args&&... args)
    {
        if constexpr( debug_mode )
        {
            out.precision( 20 );
            (out << ... << args) << std::endl;
            abort();
        }
    }
}

#ifdef better_assert
#undef better_assert
#endif
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ",  __LINE__ __VA_OPT__(,) __VA_ARGS__))         

с кодом тестированиянапример

    int a = 1;
    int b = 2;
    better_assert( a == 1 );
    better_assert( a == b, "Error: expected a == b, but a = ", a, " and b = ", b );

gcc 9.1.0 принимает этот код без проблем, но clang 8.0.0 отклонил его с сообщением об ошибке:

prog.cc:28:5: error: expected ')'
    better_assert( a == 1 );
    ^
prog.cc:22:192: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ",  __LINE__ __VA_OPT__(,) __VA_ARGS__))
                                                                                                                                                                                               ^
prog.cc:28:5: note: to match this '('
prog.cc:22:92: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ",  __LINE__ __VA_OPT__(,) __VA_ARGS__))
                                                                                           ^
prog.cc:29:5: error: expected ')'
    better_assert( a == b, "Error: expected a == b, but a = ", a, " and b = ", b );
    ^
prog.cc:22:192: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ",  __LINE__ __VA_OPT__(,) __VA_ARGS__))
                                                                                                                                                                                               ^
prog.cc:29:5: note: to match this '('
prog.cc:22:92: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ",  __LINE__ __VA_OPT__(,) __VA_ARGS__))
                                                                                           ^
2 errors generated.

Эта проблема, вероятно, связана только с gccмакросы __VA_OPT__ и __VA_ARGS__.У меня вопрос, есть ли способ сделать этот better_assert макрос переносимым с clang?

Онлайн код для вашей справки: https://wandbox.org/permlink/ggcafJ5zbGrg5ZTx


Я заметил предложение __VA_OPT__в с ++ 20.Может быть, это лучший способ решить эту проблему?

...