它会在编译时评估吗? (传递const char *作为模板参数)

时间:2016-11-08 09:25:54

标签: c++ c++11 templates boost

工作示例:

#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_filecstr_func(再次在编译时)。并且在运行时只需在failure == true时打印常量。

我的模板接受2 * BUFFER_SIZE + 1个参数,所以它的当前配置超过500个

我的榜样是这样做的吗?
我希望“使用变量专门化模板”是正确的工具。所有c-string将使用SPLIT("...")宏传递给此模板,在编译时已知。

编辑#2:
@olpa告诉我,我的例子是bug'y。我已使用最新的100%工作版重新上传。

0 个答案:

没有答案