工作示例:
#include <iostream>
#include <boost/preprocessor/config/limits.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
///////////////////////////////////////////////////////////////////////////////////////////////
// COMPILE-TIME C-STRING PROCESSING:
///////////////////////////////////////////////////////////////////////////////////////////////
#define _DEBUG_MODE_ 1
#define _ERROR_CHK_ 1
#define MY_NULLPTR nullptr
#ifdef _MSC_VER
#define __FUNC__ __FUNCTION__
#else
#define __FUNC__ __func__
#endif
///////////////////////////////////
// Configuration:
#define BUFFER_SIZE 100 // Limit: 256 // const char buffer[BUFFER_SIZE]... // you will not find any symbol with name "buffer" it is just an abstraction
#define EMPTY_CHAR '\0'
#define DEFAULT_MSG "3W3A]3Aw"
///////////////////////////////////
// Slice char[] into separate char's
constexpr __forceinline
char getCharAt (const char* cstr, unsigned int i, unsigned int l) {
return (i < l) ? cstr[i] : EMPTY_CHAR;
}
#define GET_CHAR_AT(z,n,text) , getCharAt(text, n, (sizeof(text) / sizeof(text[0])))
#define SLICE(_cstr) sizeof(_cstr)/sizeof(_cstr[0]) BOOST_PP_REPEAT(BUFFER_SIZE, GET_CHAR_AT, _cstr)
///////////////////////////////////
// fragments of code to be repeated:
#define ARG(z,n,text) , const char text ## n // repeat fragment of code n times // make list of template arguments:
#define LIST(z,n,text) text ## n, // repeat fragment of code n times: // make "body" of initializer list
///////////////////////////////////
// Repeat _macro "BUFFER_SIZE" times:
#define REPEAT_MACRO(_macro, _text) BOOST_PP_REPEAT(BUFFER_SIZE, _macro, _text)
///////////////////////////////////
// Cast to std::string:
#define CAST_TO_STRING(_cstr) ((std::string)_cstr)
///////////
///////////////////////////////////////////////////////////////////////////////////////////////
// ERRCHK:
///////////////////////////////////////////////////////////////////////////////////////////////
#define NAME_OF_ERRCHK_VARIABLE_FILE file
#define NAME_OF_ERRCHK_VARIABLE_FROM from
#define NAME_OF_ERRCHK_VARIABLE_FUNC func
#define NAME_OF_ERRCHK_VARIABLE_MSG msg
template < unsigned int line,
// unsigned int length_file, const char file0, const char file1, const char file2, ... , const char fileN // where N = BUFFER_SIZE - 1
unsigned int length_file REPEAT_MACRO(ARG, NAME_OF_ERRCHK_VARIABLE_FILE),
// unsigned int length_from, const char from0, const char from1, const char from2, ... , const char fromN // where N = BUFFER_SIZE - 1
unsigned int length_from REPEAT_MACRO(ARG, NAME_OF_ERRCHK_VARIABLE_FROM),
// unsigned int length_func, const char func0, const char func1, const char func2, ... , const char funcN // where N = BUFFER_SIZE - 1
unsigned int length_func REPEAT_MACRO(ARG, NAME_OF_ERRCHK_VARIABLE_FUNC),
// unsigned int length_msg, const char msg0, const char msg1, const char msg2, ... , const char msgN // where N = BUFFER_SIZE - 1
unsigned int length_msg REPEAT_MACRO(ARG, NAME_OF_ERRCHK_VARIABLE_MSG ) >
__forceinline
void errchk(bool failure, bool* flag_success = MY_NULLPTR) {
if (failure) {
// constexpr const char file[] = { file0, file1, file2, ... , fileN, '\0' }; // where N = BUFFER_SIZE - 1
constexpr const char file[] = { REPEAT_MACRO(LIST, NAME_OF_ERRCHK_VARIABLE_FILE) EMPTY_CHAR };
// constexpr const char from[] = { from0, from1, from2, ... , fromN, '\0' }; // where N = BUFFER_SIZE - 1
constexpr const char from[] = { REPEAT_MACRO(LIST, NAME_OF_ERRCHK_VARIABLE_FROM) EMPTY_CHAR };
// constexpr const char func[] = { func0, func1, func2, ... , funcN, '\0' }; // where N = BUFFER_SIZE - 1
constexpr const char func[] = { REPEAT_MACRO(LIST, NAME_OF_ERRCHK_VARIABLE_FUNC) EMPTY_CHAR };
// constexpr const char msg[] = { msg0, msg1, msg2, ... , msgN, '\0' }; // where N = BUFFER_SIZE - 1
constexpr const char msg[] = { REPEAT_MACRO(LIST, NAME_OF_ERRCHK_VARIABLE_MSG ) EMPTY_CHAR };
// print error:
std::cout << "File: " << NAME_OF_ERRCHK_VARIABLE_FILE << std::endl;
std::cout << "Line: " << line << std::endl;
std::cout << "From: " << NAME_OF_ERRCHK_VARIABLE_FROM << "()" << std::endl;
std::cout << "Func: " << NAME_OF_ERRCHK_VARIABLE_FUNC << std::endl;
// print message:
if(CAST_TO_STRING(msg) != CAST_TO_STRING(DEFAULT_MSG))
std::cout << "Msg: " << msg << std::endl;
// set flag:
if (flag_success)
*flag_success = false;
}
#if (_DEBUG_MODE_)
else {
}
#endif
}
///////////
///////////////////////////////////////////////////////////////////////////////////////////////
// MACROS:
///////////////////////////////////////////////////////////////////////////////////////////////
#if (_ERROR_CHK_)
//> - F stands for Flag. ERRCHK is using bool flag
//> - C stands for Class. ERRCHK is using member variables;
//> - M stands for Message ERRCHK will print user message. mesage must be in format: "my mesage" as c-string and nothing else!!! Otherwise you will see THE GRAND MOTHER OF ALL ERRORS!!!
# define ERRCHK(_failure) \
errchk <__LINE__, SLICE(__FILE__), SLICE(__FUNC__), SLICE(#_failure), SLICE(DEFAULT_MSG)> (_failure);
# define ERRCHK_F(_failure, _flag) \
errchk <__LINE__, SLICE(__FILE__), SLICE(__FUNC__), SLICE(#_failure), SLICE(DEFAULT_MSG)> (_failure, &_flag);
# define ERRCHK_C(_failure, _msg) \
errchk <__LINE__, SLICE(__FILE__), SLICE(__FUNC__), SLICE(#_failure), SLICE(DEFAULT_MSG)> (_failure, &(MY_(success)));
# define ERRCHK_M(_failure, _msg) \
errchk <__LINE__, SLICE(__FILE__), SLICE(__FUNC__), SLICE(#_failure), SLICE(_msg)> (_failure);
#else
# define ERRCHK(_failure) \
_failure;
# define ERRCHK_F(_failure) \
_failure;
# define ERRCHK_C(_failure) \
_failure;
# define ERRCHK_M(_failure) \
_failure;
#endif
///////////
///////////////////////////////////////////////////////////////////////////////////////////////
// MAIN::
///////////////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char ** argv) {
bool failure = true;
ERRCHK(failure);
getchar();
}
///////////
编辑:
基本上我想做的就是使用模板。
我希望在编译时传递所有这些字符(file0
file1
file2
...,func0
func1
func2
...)进入功能体的时间。将它们连接到c-string cstr_file
或cstr_func
(再次在编译时)。并且在运行时只需在failure == true
时打印常量。
我的模板接受2 * BUFFER_SIZE + 1
个参数,所以它的当前配置超过500个
我的榜样是这样做的吗?
我希望“使用变量专门化模板”是正确的工具。所有c-string将使用SPLIT("...")
宏传递给此模板,在编译时已知。
编辑#2:
@olpa告诉我,我的例子是bug'y。我已使用最新的100%工作版重新上传。