C++ 为什么可以';如果参数类型依赖于模板参数,编译器将推断返回类型
当我试图根据另一个模板参数在模板内选择重载集(C++ 为什么可以';如果参数类型依赖于模板参数,编译器将推断返回类型,c++,templates,template-argument-deduction,C++,Templates,Template Argument Deduction,当我试图根据另一个模板参数在模板内选择重载集(foo)的函数时,出现模板推断错误: #include <iostream> #include <string> void foo(int a){ std::cout << "int"; } void foo(double a) { std::cout << "double"; } template <typename T, typename R> void print
foo
)的函数时,出现模板推断错误:
#include <iostream>
#include <string>
void foo(int a){
std::cout << "int";
}
void foo(double a) {
std::cout << "double";
}
template <typename T, typename R>
void print(const T& data, R(*fun)(typename T::type) ) {
fun(data.value);
}
struct IntData{
using type = int;
type value;
};
int main()
{
IntData x{1};
print(x, foo);
}
这似乎表明,只要知道T
,就可以推导出R
。那么,如果两个参数都被推导出来,为什么它不起作用呢
谢谢大家! 我认为这是因为函数指针参数的返回类型是
R
注意这句话
因此,当我们询问函数的签名时,我们必须给出两个答案:
对于是函数模板专门化的函数,
签名包括返回类型
对于不是专门化的函数,返回类型不是签名的一部分
由于foo
只是一个重载函数,而void
不是foo
函数签名的一部分,R
将不帮助编译器推断正确的函数重载。因此,将foo
用作函数指针在main的范围内是不明确的。编译器通常通过匹配所提供参数的类型来解决重载问题,而函数指针本身不存在参数类型
我相信这是最健壮的解决方案,包括一个中介函数来解析以前不明确的函数指针。除了int之外,我还包括了一些其他类型,以演示在下面提到的策略中使用auto的灵活性
#include <iostream>
#include <string>
void foo(int a){
std::cout << "int" << std::endl;
}
void foo(double a) {
std::cout << "double" << std::endl;
}
bool foo(char a) {
std::cout << "char" << std::endl;
return true;
}
template <typename T, typename R>
R print(const T& data, R(*fun)(typename T::type) ) {
return fun(data.value);
}
struct IntData{
using type = int;
type value;
};
struct DoubleData{
using type = double;
type value;
};
struct CharData{
using type = char;
type value;
};
template <typename T>
auto print2(const T& data)
{
auto(*fooResolved)(typename T::type) = foo;
return print(data,fooResolved);
}
int main()
{
IntData x{1};
print2(x);
DoubleData y{1.0};
print2(y);
CharData z{'a'};
bool result = false;
std::cout << "bool before: " << result << std::endl;
result = print2(z);
std::cout << "bool after : " << result << std::endl;
}
#包括
#包括
无效foo(int a){
std::cout Chicken,meet egg!如果某个地方有另一个打印
模板呢?演绎不会从左到右进行--对每个参数独立进行演绎,然后整理结果,如果任何两个不同的参数成功但产生了冲突的演绎,则会出现错误。您应该得到完全相同的错误r如果删除const T&
parameter@AsteroidsWithWings那是不可能的relevant@M.M我不明白为什么不呢?可能会有多个函数模板可供选择,这至少在一定程度上驱动了演绎规则的构建方式,当然?@Asteroswithwings模板演绎是基于可见的内容(在声明和实例化上下文中),通常不可见的额外专门化或重载会导致程序的NDR格式错误
print<IntData>(x, foo);
#include <iostream>
#include <string>
void foo(int a){
std::cout << "int" << std::endl;
}
void foo(double a) {
std::cout << "double" << std::endl;
}
bool foo(char a) {
std::cout << "char" << std::endl;
return true;
}
template <typename T, typename R>
R print(const T& data, R(*fun)(typename T::type) ) {
return fun(data.value);
}
struct IntData{
using type = int;
type value;
};
struct DoubleData{
using type = double;
type value;
};
struct CharData{
using type = char;
type value;
};
template <typename T>
auto print2(const T& data)
{
auto(*fooResolved)(typename T::type) = foo;
return print(data,fooResolved);
}
int main()
{
IntData x{1};
print2(x);
DoubleData y{1.0};
print2(y);
CharData z{'a'};
bool result = false;
std::cout << "bool before: " << result << std::endl;
result = print2(z);
std::cout << "bool after : " << result << std::endl;
}
#include <iostream>
#include <string>
void foo(int a){
std::cout << "int";
}
void foo(double a) {
std::cout << "double";
}
template <typename T>
void print(const T& data, void(*fun)(typename T::type) ) {
fun(data.value);
}
struct IntData{
using type = int;
type value;
};
int main()
{
IntData x{1};
print(x, foo);
}
#include <iostream>
#include <string>
void foo(int a){
std::cout << "int";
}
void foo(double a) {
std::cout << "double";
}
template <typename T, typename R>
void print(const T& data, R (*fun)(T) ) {
fun(data);
}
struct IntData{
using type = int;
type value;
};
int main()
{
IntData x{1};
print(x.value, foo);
}
#include <iostream>
#include <string>
void foo(int a){
std::cout << "int" << std::endl;
}
bool foo(double a) {
std::cout << "double" << std::endl;
return true;
}
template <typename T, typename R>
R print(const T& data, R (*fun)(T) ) {
return fun(data);
}
struct IntData{
using type = int;
type value;
};
struct DoubleData{
using type = double;
type value;
};
int main()
{
IntData x{1};
print(x.value, foo);
//foo(int) does not return a value
//bool test = print(x.value, foo); // Does not compile
DoubleData y{1.0};
bool result = false;
result = print(y.value, foo);
std::cout << result << std::endl;
}
#include <iostream>
#include <string>
void foo(int a){
std::cout << "int";
}
void foo(double a) {
std::cout << "double";
}
template <typename T, typename R>
void print(const T& data, R(*fun)(typename T::type) ) {
fun(data.value);
}
struct IntData{
using type = int;
type value;
};
int main()
{
IntData x{1};
void(*fooResolved)(int) = foo;
print(x, fooResolved);
}