强制从函数中推导模板以生成常量引用(如果适用)

Force template deduction from a function to produce const references where applicable

本文关键字:引用 常量 如果 函数      更新时间:2023-10-16

在vscode 中使用 gdb 运行以下函数告诉我,T (*)(const int &, const int *, int &, int)形式函数的推导 argType 分别是intconst int *int &int。有没有办法强制编译器在呈现const Type &参数时推断const Type &?或者是否有其他方法可以以有用的方式提取该类型信息?

#include<typeinfo>
template<typename T, typename...argTypes>
void testfunc(T (*f)(argTypes...))
{
const char *a[] = { typeid(argTypes).name()... };
for(auto &av :a)
{
std::cout << av << std::endl;
}
}

编辑: 更多上下文:这个函数显然几乎没有什么作用,但是产生它的问题函数也接受了所有使用 f 运行的参数,它们不是被推导的,而是被转换的。 这给将不可复制的对象用作 const 引用带来了问题。

使用testfunc的示例如下:

#include "testfunc.h"
std::vector<bool> funcToTest(const int &a, const int *b, int &c, int d)
{
std::vector<bool> out;
out.push_back(&a == b);
out.push_back(&c == b);
out.push_back(&d == b);
return out;
}
int main()
{
// put a breakpoint here, and step in, you would see that 'a'
// describes the situation as described above.
testfunc(funcToTest);
}

这里的问题在于typeid,而不是模板推导。 如果您使用

template<typename... Ts>
struct types;
template<typename T, typename...argTypes>
void testfunc(T (*f)(argTypes...))
{
types<argTypes...>{};
}

您会收到一条很好的错误消息,例如

main.cpp: In instantiation of 'void testfunc(T (*)(argTypes ...)) [with T = std::vector<bool>; argTypes = {const int&, const int*, int&, int}]':
main.cpp:30:24:   required from here
main.cpp:12:5: error: invalid use of incomplete type 'struct types<const int&, const int*, int&, int>'
12 |     types<argTypes...>{};
|     ^~~~~
main.cpp:7:8: note: declaration of 'struct types<const int&, const int*, int&, int>'
7 | struct types;
|        ^~~~~

这表明函数参数类型已正确推导。

typeid如果类型是引用,则返回引用的类型,则返回引用的类型。 它还会删除类型上的所有 cv 限定。 这意味着

int main()
{
std::cout << typeid(int).name() << "n";
std::cout << typeid(int&).name() << "n";
std::cout << typeid(const int).name() << "n";
std::cout << typeid(const int&).name() << "n";
std::cout << typeid(volatile int).name() << "n";
std::cout << typeid(volatile int&).name() << "n";
std::cout << typeid(const volatile int).name() << "n";
std::cout << typeid(const volatile int&).name() << "n";
}

指纹

i
i
i
i
i
i
i
i