Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以';如果参数类型依赖于模板参数,编译器将推断返回类型_C++_Templates_Template Argument Deduction - Fatal编程技术网

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);
}