C++ 17标准引入了"模板推导指南".我认为它们与此版本标准中引入的构造函数的新模板参数推导有关,但我还没有看到一个简单的,常见问题解答风格的解释,它们是什么以及它们的用途.
什么是C++ 17中的模板推导指南?
为什么(以及何时)我们需要它们?
我该如何申报?
我最近接触过这个问题,答案可以概括为"这是一个非受限的背景".
具体来说,第一个说它是这样的东西,然后重定向到"细节"的标准,而第二个引用标准,这至少可以说是神秘的.
有人可以向凡人解释,比如我自己,什么是非受限的背景,什么时候发生,为什么会发生?
c++ templates template-argument-deduction argument-deduction
我正在尝试以monad风格编写语法糖std::optional
.请考虑:
template<class T>
void f(std::optional<T>)
{}
Run Code Online (Sandbox Code Playgroud)
即使存在从2到2的转换,也不能使用非可选T
1(例如an int
)调用此函数.T
std::optional<T>
有没有办法f
接受a std::optional<T>
或a T
(在调用者站点转换为可选),而没有定义过载3 ?
1) f(0)
:error: no matching function for call to 'f(int)'
和note: template argument deduction/substitution failed
,(演示).
2)因为模板参数推导不考虑转换.
3)超载是用于一个一元函数的可接受的解决方案,但开始是当你有像二进制功能的烦恼operator+(optional, optional)
,并且是用于三元疼痛,4元,等等功能.
考虑
#include <iostream>
#include <type_traits>
template <class T, class ARG_T = T&>
T foo(ARG_T v){
return std::is_reference<decltype(v)>::value;
}
int main() {
int a = 1;
std::cout << foo<int>(a) << '\n';
std::cout << foo<int, int&>(a) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我希望两种情况下的输出均为1。但在第一种情况下为0:与默认值class ARG_T = T
而不是一致class ARG_T = T&
。
我想念什么?
c++ templates function-templates template-argument-deduction argument-deduction
阅读C++ 11标准我无法完全理解以下语句的含义.例子非常受欢迎.
两组类型用于确定部分排序.对于涉及的每个模板,都有原始函数类型和转换后的函数类型.[注意:转换类型的创建在14.5.6.2中描述. - 结束注释]演绎过程使用变换后的类型作为参数模板,将另一个模板的原始类型用作参数模板.对于部分排序比较中涉及的每种类型,此过程完成两次:一次使用转换的模板-1作为参数模板,使用template-2作为参数模板,再次使用转换的模板-2作为参数模板和模板-1作为参数模板
- N3242 14.8.2.4.2
c++ templates partial-ordering c++11 template-argument-deduction
我尝试使用默认模板参数编写此函数:
template<typename A, typename B>
void func(int i1, int i2, A a, B b = 123){
...
}
Run Code Online (Sandbox Code Playgroud)
在我看来,我可以这样称呼它:func(1, 2, 3)
编译器应该从默认值推断出类型B
,int
但我得到了no instance of overloaded function
。
在这种情况下,C++ 构造是否不正确并且编译器无法推断出类型?
c++ templates default default-arguments template-argument-deduction
在下面的示例中,0
它以一种特殊的方式运行:它选择与示例函数调用所期望的不同的重载。我想知道为什么。我的理解也如下。
#include <iostream>
template<typename T>
void f(T a) {
std::cout << "first" << std::endl;
}
template<typename T>
void f(T* a) {
std::cout << "second" << std::endl;
}
int main()
{
f(0);
f<size_t>(0);
f<size_t>(0UL);
f(1);
f<size_t>(1);
}
Run Code Online (Sandbox Code Playgroud)
输出:
first
second
first
first
first
Run Code Online (Sandbox Code Playgroud)
我的理解:
f(0)
- 模板参数推导,整数文字0
是int
类型,因此f
选择第一个T=int
f<size_t>(0)
-带有整数提升的显式模板实例化,选择的类型是T=size_t
,选择第一个函数并从到提升0
(我在这里错了)int
size_t
f<size_t>(0UL)
- 与上面相同,但没有升级(0 已经是 type size_t
)
f(1)
- 与 …
c++ templates function-templates overload-resolution template-argument-deduction
我希望能够使用模板推导来实现以下目标:
GCPtr<A> ptr1 = GC::Allocate();
GCPtr<B> ptr2 = GC::Allocate();
Run Code Online (Sandbox Code Playgroud)
而不是(我现在拥有的):
GCPtr<A> ptr1 = GC::Allocate<A>();
GCPtr<B> ptr2 = GC::Allocate<B>();
Run Code Online (Sandbox Code Playgroud)
我目前的Allocate功能如下所示:
class GC
{
public:
template <typename T>
static GCPtr<T> Allocate();
};
Run Code Online (Sandbox Code Playgroud)
这将是可能敲掉多余的<A>
和<B>
?
我正在使用 C++ 库 ( strf ),其中的某处具有以下代码:
namespace strf {
template <typename ForwardIt>
inline auto range(ForwardIt begin, ForwardIt end) { /* ... */ }
template <typename Range, typename CharT>
inline auto range(const Range& range, const CharT* sep) { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
现在,我想strf::range<const char*>(some_char_ptr, some_char_ptr + some_length)
在我的代码中使用。但是如果我这样做,我会收到以下错误(使用 CUDA 10.1 的 NVCC):
error: more than one instance of overloaded function "strf::range" matches the argument list:
function template "auto strf::range(ForwardIt, ForwardIt)"
function template "auto strf::range(const Range &, const CharT *)" …
Run Code Online (Sandbox Code Playgroud) c++ nvcc overload-resolution c++11 template-argument-deduction
下面的代码段在 vc++ 和 clang++ 中编译得很好,但在 gcc (inc 9.2) 上失败,除非我添加一个显式的强制转换。哪个编译器就在这里?
#include <initializer_list>
template<typename T>
void Task(void) {}
int main()
{
for(auto p_task: {&Task<int>}) {} // error
// for(auto p_task: {static_cast<void (*)(void)>(&Task<int>)}) {} // ok
}
Run Code Online (Sandbox Code Playgroud)
#include <initializer_list>
template<typename T>
void Task(void) {}
int main()
{
for(auto p_task: {&Task<int>}) {} // error
// for(auto p_task: {static_cast<void (*)(void)>(&Task<int>)}) {} // ok
}
Run Code Online (Sandbox Code Playgroud)
c++ templates initializer-list template-argument-deduction c++17