C++11 中是否有模板来推断将值传递给函数时要使用的最佳类型
Is there a template in C++11 to deduce the optimal type to use when passing a value to a function?
我想写一个模板函数
template <typename T>
void f( T v );
这样,如果v
足够小,它将按值传递,否则通过对常量的引用传递。为此,我使用了一个小帮手
template <typename T, bool>
struct parameter_helper;
template <typename T>
struct parameter_helper<T, true> {
typedef T type;
};
template <typename T>
struct parameter_helper<T, false> {
typedef const T& type;
};
template <typename T>
struct parameter {
typedef typename parameter_helper<T, sizeof(T) <= sizeof(void*)>::type type;
};
在过去,我可以拥有
template <typename T>
void f( typename parameter<T>::type v );
现在,在 C++11 中:这种帮助程序模板是否仍然有意义,或者是否有更好的方法来达到相同的效果?是否已经有现成的模板?我检查了<type_traits>
但找不到任何似乎相关的内容。
使用 C++11,您可以定义别名模板并节省一些键入时间。
template<typename T>
using parameter_t = typename parameter<T>::type;
然后将其用作
template <typename T>
void f( parameter_t<T> v );
AFAIK,标准库中没有内置任何内容。此外,您将失去实现这种特征的模板参数推导,在我看来,这会大大降低其效用。
我认为 C++11 在这方面没有任何新内容,但是......
我的建议是实际内化基本规则并直接使用它们。在某些情况下,即使类型小于 4 个字节,您也可能希望通过 const 引用传递(该函数将存储引用以供以后使用,尽管它不应该更改字段,但它需要访问更新的值(。
相反,如果函数无论如何都要创建副本,您可能希望按值传递,以便在界面中完成复制,并且可以省略副本或将其更改为移动操作,从而可能降低操作的成本。
我想编写一个模板函数
template <typename T> void f( T v );
这样,如果
v
足够小,它将按值传递,否则通过对常量的引用传递。
编译器可以足够聪明,可以在没有任何模板魔术的情况下做正确的事情,特别是如果函数f
可以内联。我总是会f
实现为
template <typename T>
void f(const T& v);
并相信编译器会将其转换为副本,如果副本更便宜。
下面是一个示例:
extern volatile int k;
extern volatile int m;
static void f(const int& j) noexcept { // or f(const int j)
for (int i=0; i<j; ++i) {
m = i;
}
}
void g() noexcept {
int j = k;
f(j);
}
我运行了clang++ -O3 -std=c++11 -S -emit-llvm filename.cpp
,生成的程序集(据我所知(是相同的。
通过引用传递:
@k = external global i32
@m = external global i32
; Function Attrs: nounwind uwtable
define void @_Z1gv() #0 {
entry:
%0 = load volatile i32* @k, align 4, !tbaa !0
%cmp3.i = icmp sgt i32 %0, 0
br i1 %cmp3.i, label %for.body.i, label %_ZL1fRKi.exit
for.body.i: ; preds = %entry, %for.body.i
%i.04.i = phi i32 [ %inc.i, %for.body.i ], [ 0, %entry ]
store volatile i32 %i.04.i, i32* @m, align 4, !tbaa !0
%inc.i = add nsw i32 %i.04.i, 1
%exitcond = icmp eq i32 %inc.i, %0
br i1 %exitcond, label %_ZL1fRKi.exit, label %for.body.i
_ZL1fRKi.exit: ; preds = %for.body.i, %entry
ret void
}
按值传递:
@k = external global i32
@m = external global i32
; Function Attrs: nounwind uwtable
define void @_Z1gv() #0 {
entry:
%0 = load volatile i32* @k, align 4, !tbaa !0
%cmp3.i = icmp sgt i32 %0, 0
br i1 %cmp3.i, label %for.body.i, label %_ZL1fi.exit
for.body.i: ; preds = %entry, %for.body.i
%i.04.i = phi i32 [ %inc.i, %for.body.i ], [ 0, %entry ]
store volatile i32 %i.04.i, i32* @m, align 4, !tbaa !0
%inc.i = add nsw i32 %i.04.i, 1
%exitcond.i = icmp eq i32 %inc.i, %0
br i1 %exitcond.i, label %_ZL1fi.exit, label %for.body.i
_ZL1fi.exit: ; preds = %for.body.i, %entry
ret void
}
如果f
未内联,则程序集会有所不同。
相关文章:
- 为什么在我的函数类型后使用引用运算符 (&) 允许我修改它返回的值?
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 是否有任何建议来统一函数类型限定符并简化可恶的函数类型?
- 关于 C++ 中的函数类型定义
- 用于检测函数类型是否为否的特征
- 函数类型参数的模板参数推导
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++无效的函数类型转换
- STL 函数和函数类型与函数指针类型
- 如何将result_of与函数类型定义一起使用
- 将模板(没有规范)传递给 std::thread() 会出现错误:<未解析的重载函数类型>匹配错误
- C++ 编译错误:gnu_printf是无法识别的格式函数类型
- 专门用于"direct"函数类型(与函数指针类型相对)
- 将函数类型作为模板参数传递不会编译
- 通过参数传递 lambda(无函数类型模板)
- 如何在模板参数中分离函数类型返回类型和参数
- 为什么比较函数类型需要指定为模板参数?
- 带有限定符的函数类型定义用例
- 如何声明对函数类型的常量引用
- 非类型模板参数允许各种函数类型?