C++ 字符串文字和模板函数的多个版本
假设我有一个模板函数:C++ 字符串文字和模板函数的多个版本,c++,c++11,C++,C++11,假设我有一个模板函数: template<typename... Args> void my_log_function(Args&&... args) { // Work, work, work. } 由于字符串文本的类型是const char[n],我相信这将创建大量my_log_函数的实例化(Visual Studio Intellisense似乎建议这样做)。有人认为这是个问题吗?会吗?可以防止吗?是的,这将创建一个不同的类模板实例。它们应该只在通过引
template<typename... Args>
void my_log_function(Args&&... args)
{
// Work, work, work.
}
由于字符串文本的类型是
const char[n]
,我相信这将创建大量my_log_函数的实例化(Visual Studio Intellisense似乎建议这样做)。有人认为这是个问题吗?会吗?可以防止吗?是的,这将创建一个不同的类模板实例。它们应该只在通过引用传递的数组的大小上有所不同,如果它们的数组实际上不再用作数组,那么生成的代码应该是相同的。据我所知,VC++可以折叠相同的代码。但是,如果类型被大量传播,它可能会产生代码膨胀
防止代码膨胀的一种方法是有条件地衰减类型,并转发到另一个执行实际工作的模板。我认为这应该起作用:
template <typename... Args>
void my_real_log_function(Args&&... args) {
// real implementation goes here
}
template <typename T>
struct decay_array {
typedef typename std::condition<
std::is_array<typename std::remove_reference<T>::type>::value,
typename std::decay<T>::type,
T>::type type;
};
template <typename... Args>
void my_log_function(Args&&... args) {
my_real_log_function(std::forward<typename std::decay_array<Args>::type>(args)...);
}
模板
void my_real_log_函数(Args&&…Args){
//真正的实现就在这里
}
模板
结构衰变数组{
typedef typename std::condition<
std::is_array::value,
typename std::Decation::type,
T> ::类型类型;
};
模板
void my_log_函数(Args&&…Args){
my_real_log_函数(std::forward(args)…);
}
仅使用typename std::decay::type
的原始版本不起作用,因为它会将对非数组的引用转换为不需要的值。解决方案不是在这样的函数中实现“work,work,work”。将变量参数整理成更规范的形式,并将工作交给非模板
注意膨胀,记住模板系统是为生成内联函数而设计的。my_log\u函数(+“1”)
将Args…
推断为const char*
(使用一元+
);类似地,您可以将工作分派到另一个模板,传递衰减的参数(目的是消除/内联最初调用的函数)DyP:Nice trick!但我认为这会让很多人感到困惑…@Potatoswatter:如果某些参数很大和/或不可复制,那么通过我的值传递它们是不可能的。@DyP:是的,你是对的:std::decation
太激进了,也会删除引用。似乎,只有在传递对数组的引用时,它才会衰减,从而使委托更有趣。@Potatoswatter:同意。我没说它有用。。。我把代码改为当参数是数组时只使用std::decay
——我想。不过,将数组转换为指针,然后将其委托给另一个函数是一种通用方法。由于这可能是一种常见的需要,因此可能值得研究如何使此操作变得简单。好的……新代码具有不平衡的尖括号和条件
,而不是条件
。typename std::remove\u reference::value
可能应该是typename std::remove\u reference::type>:value
平衡支架
template <typename... Args>
void my_real_log_function(Args&&... args) {
// real implementation goes here
}
template <typename T>
struct decay_array {
typedef typename std::condition<
std::is_array<typename std::remove_reference<T>::type>::value,
typename std::decay<T>::type,
T>::type type;
};
template <typename... Args>
void my_log_function(Args&&... args) {
my_real_log_function(std::forward<typename std::decay_array<Args>::type>(args)...);
}