2017-09-19 1 views
0

한편으로는 매개 변수 수를 분석 할 수 있어야하지만 다른 한편으로는 항상 __func__ 및 과 함께 전달되는 로깅 함수를 만듭니다. 호출 객체). log_device_message_template(this,__func__,some format,some parameters)Variadic 템플릿 및 가변 함수 조합

그래서 내가 추가 한 매크로 :

#define log_api_call(format, ...)                                       \ 
    log_device_message_template(                         \ 
     this, __func__, "%s::%s(" format ")", ##__VA_ARGS__) 

나는이

template<typename... Args> 
void 
log_device_message_template(const class *object, 
       char const *func, 
       char const *const format, 
       Args const &... args)noexcept 
{ 
log(format, to_str(object).c_str(),format, to_str(args).c_str()...); 
} 

처럼 가변 인자 템플릿을 사용하는 경우

이 같은 log_device_message_template를 호출해야 문제는 내가 잘못된 포맷으로 인해 seg 오류가 발생한다는 것입니다. 어디에. 여기

로거 테스트 파이썬 테스트에서 오류가 ... 가변 인자 템플릿의 사용으로 인해 작동하지 않습니다 __attribiute의 __ (형식) 추가 : 여기

lookup in file=***** [0] 
    28371: symbol=_ZN5***6logger27log_device_message_templateIINS_14*****E13****EEEvNS_21logger_component_eENS_17logger_level_eEPKcPKNS_9objectES7_DpRT_; lookup in file=**** [0] 
    28371: ****: error: symbol lookup error: undefined symbol: _ZN5***6logger27log_device_message_templateIINS_14****E13****EEEvNS_21logger_component_eENS_17logger_level_eEPKcPKNS_9objectES7_DpRT_ (fatal) 
+3

아마도 오타이지만 매크로의 매개 변수 순서가 엉망입니다. – Holt

+0

심볼 검색 오류가 segfault가 아닙니다. 그것은 컴파일되지 않은'log_device_message_template' 인스턴스화를 호출하려고 시도하는 것 같습니다. 인스턴스화가 존재하지 않는 이유는 누구나 추측 할 수 있습니다. 아마도 파이썬 라이브러리가이 라이브러리를 감싸는 세부 사항을보아야 할 것이다. – cdhowie

답변

0

을 다른 방법을 것은 깔끔하게하는 접근하기 매크로를 피합니다.

참고이 경우 로그 레코드를 stdout으로 내보내고 있지만 쉽게 변경할 수 있습니다. 또한 std::ostringstream을 사용하여 로그 메시지를 작성합니다. 성능면에서 유명하지 않으므로 커스터마이징 시점을 고려해야합니다.

#include <iostream> 
#include <sstream> 
#include <tuple> 
#include <utility> 

// define a constant index type 
template<std::size_t N> using index_c = std::integral_constant<std::size_t, N>; 

// emitting an item at index 0 has no prefix  
template<class T> 
void emit_item(std::ostream &os, index_c<0>, T const &t) 
{ 
    os << t; 
} 


// emitting an item at index N (!= 0) has a comma prefix 
template<std::size_t N, class T> 
void emit_item(std::ostream &os, index_c<N>, T const &t) 
{ 
    os << ", " << t; 
} 

// emit args 0 .. N-1 
template<class Tuple, std::size_t...Is> 
void emit_arglist(std::ostream &sink, Tuple &&tuple, std::index_sequence<Is...>) 
{ 
    using expand = int[]; 
    void(expand{0, 
       (emit_item(sink, index_c<Is>(), std::get<Is>(tuple)), 0)... 
    }); 

}; 

// emitting a 'more' at index 0 has a prefix 
template<class T> 
void emit_more(std::ostream &os, index_c<0>, T const &t) 
{ 
    os << " : " << t; 
} 

// emitting a 'more' at index N (!= 0) has a space prefix 
template<std::size_t N, class T> 
void emit_more(std::ostream &os, index_c<N>, T const &t) 
{ 
    os << " " << t; 
} 

template<class Tuple, std::size_t...Is> 
void emit_more(std::ostream &sink, Tuple &&tuple, std::index_sequence<Is...>) 
{ 
    using expand = int[]; 
    void(expand{0, 
       (emit_more(sink, index_c<Is>(), std::get<Is>(tuple)), 0)... 
    }); 

}; 

template<typename... Args, typename ...MoreStuff> 
std::string 
make_log_string(const char *object, 
       char const *func, 
       std::tuple<Args const &...> const& args, 
       MoreStuff&&...morestuff) noexcept 
{ 
    std::ostringstream ss; 
    ss << object << "::" << func << '('; 
    emit_arglist(ss, args, std::make_index_sequence<sizeof...(Args)>()); 
    ss << ')'; 
    emit_more(ss, std::tie(morestuff...), std::make_index_sequence<sizeof...(MoreStuff)>()); 
    return ss.str(); 
} 

// syntactic sugar for indicating arguments  
template<class...Arg> 
decltype(auto) args(Arg const&...args) 
{ 
    return std::tie(args...); 
} 


int main() 
{ 
    int a = 0, b = 1, c = 2; 
    std::string sa = "xxx", sb = "yyy", sc = "zzz"; 

    const char* Class = "foo"; 
    const char* Func = "var"; 

    std::cout << make_log_string(Class, Func, args(a, b, c)) << std::endl; 
    std::cout << make_log_string(Class, Func, args(sa, b, sc)) << std::endl; 
    std::cout << make_log_string(Class, Func, args(sa, b, sc), "more stuff") << std::endl; 
    std::cout << make_log_string(Class, Func, args(), "empty", "argument", "list") << std::endl; 

} 

예상 출력 :

std::cout << make_log_string(method(Class, Func)(a, b, c)) << std::endl; 
std::cout << make_log_string(method(Class, Func)(sa, b, sc)) << std::endl; 
std::cout << make_log_string(method(Class, Func)(sa, b, sc), "more stuff") << std::endl; 
std::cout << make_log_string(method(Class, Func)(), "empty", "argument", "list") << std::endl; 
:
foo::var(0, 1, 2) 
foo::var(xxx, 1, zzz) 
foo::var(xxx, 1, zzz) : more stuff 
foo::var() : empty argument list 

그리고 좀 더 보일러와

우리가 이것을 쓸 수있는 당신이 접근 방식을 좋아하는 경우에

그러나, 이것은 당신이 시작할 수 있어야

여기에 있습니다 :

#include <iostream> 
#include <sstream> 
#include <tuple> 
#include <utility> 

template<std::size_t N> using index_c = std::integral_constant<std::size_t, N>; 

template<class T> 
void emit_item(std::ostream &os, index_c<0>, T const &t) 
{ 
    os << t; 
} 

template<std::size_t N, class T> 
void emit_item(std::ostream &os, index_c<N>, T const &t) 
{ 
    os << ", " << t; 
} 

template<class Tuple, std::size_t...Is> 
void emit_arglist(std::ostream &sink, Tuple &&tuple, std::index_sequence<Is...>) 
{ 
    using expand = int[]; 
    void(expand{0, 
       (emit_item(sink, index_c<Is>(), std::get<Is>(tuple)), 0)... 
    }); 

}; 

template<class T> 
void emit_more(std::ostream &os, index_c<0>, T const &t) 
{ 
    os << " : " << t; 
} 

template<std::size_t N, class T> 
void emit_more(std::ostream &os, index_c<N>, T const &t) 
{ 
    os << " " << t; 
} 

template<class Tuple, std::size_t...Is> 
void emit_more(std::ostream &sink, Tuple &&tuple, std::index_sequence<Is...>) 
{ 
    using expand = int[]; 
    void(expand{0, 
       (emit_more(sink, index_c<Is>(), std::get<Is>(tuple)), 0)... 
    }); 

}; 

template<class...Args> 
struct method_with_args; 

struct method 
{ 
    constexpr method(const char* c, const char* f) : klass(c), func(f) {} 
    const char* klass; 
    const char* func; 

    template<class...Args> 
    auto operator()(Args const&...args) -> method_with_args<Args...>; 

    friend std::ostream& operator<<(std::ostream& os, const method& m) 
    { 
     return os << m.klass << "::" << m.func; 
    } 
}; 

template<class...Args> 
struct method_with_args 
{ 
    friend std::ostream& operator<<(std::ostream& os, method_with_args const& ma) 
    { 
     os << ma.m << '('; 
     emit_arglist(os, ma.args, std::make_index_sequence<sizeof...(Args)>()); 
     return os << ')'; 
    } 

    method m; 
    std::tuple<Args const&...> args; 
}; 

template<class...Args> 
auto method::operator()(Args const&...args) -> method_with_args<Args...> 
{ 
    return method_with_args<Args...>{*this, std::tie(args...)}; 

} 

struct function 
{ 
    const char* name; 
}; 

template<typename Method, typename ...MoreStuff> 
std::string 
make_log_string(Method m, 
       MoreStuff &&...morestuff) noexcept 
{ 
    std::ostringstream ss; 
    ss << m; 
    emit_more(ss, std::tie(morestuff...), std::make_index_sequence<sizeof...(MoreStuff)>()); 
    return ss.str(); 
} 


int main() 
{ 
    int a = 0, b = 1, c = 2; 
    std::string sa = "xxx", sb = "yyy", sc = "zzz"; 

    const char *Class = "foo"; 
    const char *Func = "var"; 

    std::cout << make_log_string(method(Class, Func)(a, b, c)) << std::endl; 
    std::cout << make_log_string(method(Class, Func)(sa, b, sc)) << std::endl; 
    std::cout << make_log_string(method(Class, Func)(sa, b, sc), "more stuff") << std::endl; 
    std::cout << make_log_string(method(Class, Func)(), "empty", "argument", "list") << std::endl; 
} 
관련 문제