推断大多数模板对象的参数,但在调用模板函数时对其他对象显式
Inferring parameter of most template objects, but being explicit with others when calling a template function?
我注意到,当传递给函数时,现代C++(C++11等(有时可以推断模板对象的int
模板参数,而无需使用大括号显式传递int
值。
但是,如果我想要一个函数参数:
bitset<N_OLD>
将int
模板参数自动推断为函数输入,函数返回值:
bitset<N_NEW>
在使用大括号或大小写调用函数时明确指定。这可能吗?示例:
#include <bitset>
using namespace std;
// expand or truncate bitset without sign extension
template<int N_NEW, int N_OLD>
bitset<N_NEW>
bresize(const bitset<N_OLD> value)
{
return bitset<N_NEW> {value.to_ullong() & ((1<<N_NEW)-1) };
}
例如:
bitset<16> x {0xABCD};
// version explicit everything (Not what I want)
auto y2 = bresize<32, 16>(x);
//Inference Attempt #1
auto y1 = bresize<32>(x);
//Inference Attempt #2
bitset<32> y3 = bresize(x);
//Inference Attempt #3
auto y4 = (bitset<32>)bresize(x);
我只是想了解在上述场景中推断模板大小参数时的规则是什么。目标是尽可能多地推断bitset
的输入大小,但要明确输出大小。这在C++11中可能吗?
我将给出一个通用答案,然后向您展示如何将其应用于您的案例。
不能仅从返回类型推导模板参数。
示例1
template <class T, class R>
auto foo(T) -> R;
CCD_ 5可以,而不能。因此,在调用foo
时,您需要始终保持明确。
由于R
在模板参数中位于T
之后,这意味着在指定R
时也需要指定T
,即使T
是可扣除的,例如foo<int, double>(24)
。
解决方案非常简单:将不可推导的模板参数放在第一位:
template <class R, class T>
auto bar(T) -> R;
你可以这样称呼它:
bar<double>(24); // R explicit to double, T deduced as int from the parameters
示例2
template <class T, class U>
auto foo(T, U) -> U
这里可以推导出CCD_ 13,因为它可以从参数中推导出来。
示例3
如果不可扣除模板参数依赖于另一个可扣除模板的参数,则您可以根据可扣除参数计算:
template <class T>
auto foo(T) -> std::decay_t<T>
您的案例
首先,std::bitset
的模板参数类型是std::size_t
,而不是int
。仅此一项就将导致扣除问题。先解决这个问题。
接下来要确保的是首先要有不可扣除的模板参数:
template<std::size_t N_NEW, std::size_t N_OLD>
std::bitset<N_NEW>
bresize(std::bitset<N_OLD> value) { /* ... */ }
然后您可以调用bresize
作为:
bresize<32>(x);
此外,如果N_NEW
可以是根据N_OLD
计算的constexpr
,那么您可以完全跳过显式参数:
template<std::size_t N_OLD>
std::bitset<N_OLD * 2>
bresize(std::bitset<N_OLD> value) { /* ... */ }
或
template<std::size_t N_OLD, std::size_t N_NEW = N_OLD * 2>
std::bitset<N_NEW>
bresize(std::bitset<N_OLD> value) { /* ... */ }
或
constexpr auto new_width(std::size_t old_width) => std::size_t
{
return old_width * 2;
/* or any constexpr allowed body */
};
template<std::size_t N_OLD>
std::bitset<new_width(N_OLD)>
bresize(std::bitset<N_OLD> value) { /* ... */ }
或
template<std::size_t N_OLD, std::size_t N_NEW = new_width(N_OLD)>
std::bitset<N_NEW>
bresize(std::bitset<N_OLD> value) { /* ... */ }
一些小的离题挑剔:const T
作为一个参数没有多大意义。使用const T&
或T
。
相关文章:
- 如何创建对象函数指针C++映射?
- 为什么我可以改变常量对象中的成员变量,这是返回常量对象函数的结果?
- 如何将对象函数的实例传递给另一个函数
- 调用模板函数的问题"No matching function for call"参数:迭代器、对象函数
- makefile对我的名称空间对象/函数/构造函数的不确定引用
- 将对象函数转换为函数指针
- 非对象函数/类函数C++
- 线程对象函数 C++
- C 将成员对象函数分配给类成员功能
- 使用基本指针调用派生对象函数
- 可以(通过编译器)使用多少个线程来初始化全局对象(函数main之前)
- C++类对象函数
- 对对象::函数的未定义引用
- 无法弄清楚将多个对象函数作为单独的线程调用的语法
- 在提升作用域出口中调用对象函数
- 使用基指针来使用派生对象函数
- 在for_each lambda 中调用对象函数
- C++:: 模板函数 - 从对象函数获取对象的地址
- Qt5 未解析的外部静态元对象函数
- 通过变量使用对象和对象函数