使用一个参数进行模板参数推导?

s4y*_*s4y 7 c++ templates template-argument-deduction

假设我有一个模板函数,assign().它接受一个指针和一个值,并将值赋给指针的目标:

template <typename T> void assign(T *a, T b) { *a = b; }

int main() {
    double i;
    assign(&i, 2);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我总是希望T从第一个参数推断出来,但看起来我没有做好表达这一点.2的类型是int,所以:

deduce.cpp:5:5: error: no matching function for call to 'assign'
    assign(&i, 2);
    ^~~~~~
deduce.cpp:1:28: note: candidate template ignored: deduced conflicting types for parameter 'T' ('double' vs. 'int')
template  void assign(T *a, T b) { *a = b; }

有没有办法可以声明assign()第二个参数不参与模板参数推导?

Ben*_*igt 13

使用两个类型参数可能是最好的选择,但是如果你真的只想从第一个参数执行演绎,只需使第二个不可推导:

template<typename T>
void assign( T* a, typename std::identity<T>::type b );
Run Code Online (Sandbox Code Playgroud)

该答案的早期版本建议使用C++ 11中引入的模板别名功能.但模板别名仍然是一种可推导的背景.阻止std::identity和减少std::remove_reference推理的主要原因是模板类可以是专用的,因此即使你有一个模板类型参数的typedef,另一个特化也可能有一个相同类型的typedef.由于可能存在歧义,因此不会进行演绎.但模板别名排除了特殊化,因此仍然会发生演绎.


小智 0

C++20std::type_identity可用于建立非推导上下文:

#include <type_traits>

template <typename T>
void assign(T *a, std::type_identity_t<T> b) {
    *a = b;
}

int main() {
    double i;
    assign(&i, 2);
}
Run Code Online (Sandbox Code Playgroud)

演示