变异模板和变异功能组合
Variadic templates and variadic functions combination
我正在创建一个记录函数,一方面需要能够解析任何数量的参数,但另一方面,将始终使用__func__ and > this(调用对象)。
如果我使用仅 variadic模板像这样
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
: log_device_message_template(this,__func__,some format,some parameters)
所以我添加了宏:
#define log_api_call(format, ...)
log_device_message_template(
this, __func__, "%s::%s(" format ")", ##__VA_ARGS__)
问题是我遇到了SEG错误,这可能是由于某处的格式不好。添加__attribiute __(格式)由于使用variadic模板而行不通...
这是python测试测试的错误:
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)
这是对其进行整齐避免宏的另一种方法。
请注意,在这种情况下,我将日志记录发射到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;
}
预期输出:
foo::var(0, 1, 2)
foo::var(xxx, 1, zzz)
foo::var(xxx, 1, zzz) : more stuff
foo::var() : empty argument list
,使用更多样式板,我们可以写下:
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;
这里是:
#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;
}
相关文章:
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 可组合的lambda/std::函数与std::可选
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 混合组合和继承的C++问题
- 我需要将多个函数组合为一个函数
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 通过组合不同的类型来创建唯一的id
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 模板元编程:如何将参数包组合成新的参数包
- 检查向量是否具有所有可能的字符组合
- 如何在加密++中将两个源组合成新的源
- 根中的组合
- 更改 C++ 中的组合分类变量
- 错误:(-210:不支持的格式或格式组合)功能'create'中的硬件视频解码器不支持视频源
- 组合字符串不适用于 libCurl,C++
- 测试两个类型列表中的所有组合
- 将多个 for 循环组合成单个迭代器
- 2个模板构造函数的组合构建与变异模板.如何
- 组合类模板默认参数和变异参数
- 变异模板和变异功能组合