What set of functions is considered when resolving overloaded functions assigning to default parameter values?

大兔子大兔子 提交于 2019-12-10 01:14:09

问题


Consider the function bar below, whose parameter has a default value initialized from an invocation of an overloaded foo:

#include <iostream>

int foo(int x)
{
  std::cout << "foo(int)" << std::endl;
  return 0;
}

template<typename T>
void bar(T a, int x = foo(T(0))) {}

double foo(double x)
{
  std::cout << "foo(double)" << std::endl;
  return 0;
}

int main()
{
  bar<int>(1);
  bar<double>(1);
  return 0;
}

I expect this program to output

foo(int)
foo(double)

corresponding to foo's two overloads which are visible at bar's instantiation.

Instead, when compiled with g++-4.6, the output is

$ g++-4.6 -std=c++0x test.cpp; ./a.out 
foo(int)
foo(int)

Is the set of overloads considered when implementing a default parameter value different from normal overload resolution? Is this case described in the ISO C++ standard?


回答1:


Here is what the standard says about this. First, in 8.3.6 [dcl.fct.default] paragraph 5:

... The names in the default argument are bound, and the semantic constraints are checked, at the point where the default argument appears. Name lookup and checking of semantic constraints for default arguments in function templates and in member functions of class templates are performed as described in 14.7.1. ...

Further in 14.7.1 [temp.inst] paragraph 12:

If a function template f is called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument is done as if the default argument had been an initializer used in a function template specialization with the same scope, the same template parameters and the same access as that of the function template f used at that point. This analysis is called default argument instantiation. The instantiated default argument is then used as the argument of f.

I'm not quite sure what this exactly says. I can see both interpretations in this text. In case it matters, I think EDG agrees with gcc and clang.




回答2:


This program suggests that the set of functions considered follows normal overload resolution rules:

#include <iostream>

struct type1 {};
struct type2 {};

int foo(type1 x)
{
  std::cout << "foo(type1)" << std::endl;
  return 0;
}

template<typename T>
void bar(int x = foo(T())) {}

int foo(type2 x)
{
  std::cout << "foo(type2)" << std::endl;
  return 0;
}

int main()
{
  bar<type1>();
  bar<type2>();
  return 0;
}

When compiled with g++-4.6, this program outputs:

$ g++ test_2.cpp ; ./a.out 
foo(type1)
foo(type2)

In other words, foo is resolved via ADL when bar is instantiated.

The behavior for the code from the OP seems to be that ADL does not apply to primitives such as int and double, so the only overloads considered are those declared before foo's call. The odd MSVC behavior seems to be non-standard.




回答3:


Maybe it's because you declared&defined the overloaded function "foo(double)" after the template, so it doesn't know anything about its existence . ->structured programming. I'd suggest:

#include <iostream>

int foo(int x)
{
std::cout << "foo(int)" << std::endl;
  return 0;
}

double foo(double x)
{
std::cout << "foo(double)" << std::endl;
return 0;
}

template<typename T>
void bar(T a, int x = foo(T(0))) {}



int main()
{
bar<int>(1);
bar<double>(1);
return 0; 
}


来源:https://stackoverflow.com/questions/13484308/what-set-of-functions-is-considered-when-resolving-overloaded-functions-assignin

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!