命名空间中的重载解析 [英] Overload Resolution in a Namespace

查看:217
本文介绍了命名空间中的重载解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

工作示例1:没有命名空间

p>

  class C {}; 

inline void overloaded(int){}

template< typename T> void try_it(T value){
overloaded(value);
}

inline void overloaded(C){}


int main()
{
try_it(1) ;
C c;
try_it(c);
return 0;工作示例2:在模板之前定义的所有重载。

  class C {}; 

命名空间n {
inline void overloaded(int){}
inline void overloaded(C){}
}

template<类型名T> void try_it(T value){
n :: overloaded(value);
}

int main()
{
try_it(1);
C c;
try_it(c);
return 0;
}

Broken Example 3:Some overloads after the template

  class C {}; 

namespace n {
inline void overloaded(int){}
}

template< typename T> void try_it(T value){
n :: overloaded(value);
}

命名空间n {
inline void overloaded(C){}
}

int main()
{
try_it(1);
C c;
try_it(c); // /tmp/test.cpp:在函数'void try_it(T)[with T = C]':
// /tmp/test.cpp:19:15:从这里实例化
/ / /tmp/test.cpp:8:7:错误:无法将参数'1'的'C'转换为'int'到'void n :: overloaded(int)'

return 0;
}

为什么会这样?我需要做什么才能在模板函数后声明或定义一个重载?

解决方案

这是一个问题



在表达式 overloaded(value); 中,名称 overloaded 依赖于[temp.dep] / 1。



据我所知,在表达式 n :: overloaded(value),名称 overloaded (在 id-expression n






依赖名称查找非常特殊,[temp.dep.res] / 1


在解析依赖名称时,会考虑以下来源的名称: / p>


  • 在模板定义点可见的声明。

  • 与命名空间来自实例化上下文和定义上下文的函数参数的类型。


在文件末尾的函数模板的实例化点,因此可以找到来自相关命名空间的所有声明。)



对于非依赖名称,正常查找规则



因此,要查找在模板定义之后声明为的名称,它们必须依赖于<






一个简单的解决方法是将另一个参数引入到函数 overloaded 或换行参数,使得此函数的参数之一具有命名空间 n associated:

  #include< iostream> 

class C {};

namespace n {
struct ADL_helper {};
inline void overloaded(int,ADL_helper = {})
{std :: cout< n :: overloaded(int,..)< std :: endl; }
}

template< typename T> void try_it(T value){
overloaded(value,n :: ADL_helper {});
}

命名空间n {
inline void overloaded(C,ADL_helper = {})
{std :: cout< n :: overloaded(C,..)< std :: endl; }
}

int main()
{
try_it(1);
C c;
try_it(c);
}

或者:

 命名空间n {
template<类型名T>
struct wrapper {T elem; };

inline void overloaded(wrapper< int>)
{std :: cout< n :: overloaded(wrapper< int>)< std :: endl; }
}

template< typename T> void try_it(T value){
overloaded(n :: wrapper< T> {value});
}

命名空间n {
inline void overloaded(wrapper< C>)
{std :: cout< n :: overloaded(wrapper< C>)< std :: endl; }
}


I am attempting to call an overloaded function inside a namespace and am struggling a bit.

Working Example 1: No namespace

class C {};

inline void overloaded(int) {}

template<typename T> void try_it(T value) {
  overloaded(value);
}

inline void overloaded(C) {}


int main()
{
  try_it(1);
  C c;
  try_it(c);
  return 0;
}

Working Example 2: All overloads defined before template

class C {};

namespace n {
  inline void overloaded(int) {}
  inline void overloaded(C) {}
}

template<typename T> void try_it(T value) {
  n::overloaded(value);
}

int main()
{
  try_it(1);
  C c;
  try_it(c);
  return 0;
}

Broken Example 3: Some overloads after the template

class C {};

namespace n {
  inline void overloaded(int) {}
}

template<typename T> void try_it(T value) {
  n::overloaded(value);
}

namespace n {
  inline void overloaded(C) {}
}

int main()
{
  try_it(1);
  C c;
  try_it(c); // /tmp/test.cpp: In function ‘void try_it(T) [with T = C]’:
             // /tmp/test.cpp:19:15:   instantiated from here
             // /tmp/test.cpp:8:7: error: cannot convert ‘C’ to ‘int’ for argument ‘1’ to ‘void n::overloaded(int)’

  return 0;
}

Why is this the case? What do I need to do to be able to declare or define an overload after the template function?

解决方案

This is a problem of dependent name lookup.

In the expression overloaded(value);, the name overloaded is dependent as per [temp.dep]/1.

As far as I know, in the expression n::overloaded(value), the name overloaded (in the id-expression n::overloaded) is not dependent.


Dependent name lookup is very peculiar, [temp.dep.res]/1

In resolving dependent names, names from the following sources are considered:

  • Declarations that are visible at the point of definition of the template.
  • Declarations from namespaces associated with the types of the function arguments both from the instantiation context and from the definition context.

(There's a point of instantiation for function templates at the end of the file, so all declarations from associated namespaces can be found.)

For non-dependent names, the normal lookup rules apply (lookup from the definition context).

Therefore, to find names declared after the definition of the template, they have to be dependent and be found via ADL.


A simple workaround is to introduce another parameter to the function overloaded or wrap the argument, such that one of the arguments of this function has namespace n associated:

#include <iostream>

class C {};

namespace n {
  struct ADL_helper {};
  inline void overloaded(int, ADL_helper = {})
  { std::cout << "n::overloaded(int,..)" << std::endl; }
}

template<typename T> void try_it(T value) {
  overloaded(value, n::ADL_helper{});
}

namespace n {
  inline void overloaded(C, ADL_helper = {})
  { std::cout << "n::overloaded(C,..)" << std::endl; }
}

int main()
{
  try_it(1);
  C c;
  try_it(c);
}

alternatively:

namespace n {
  template < typename T >
  struct wrapper { T elem; };

  inline void overloaded(wrapper<int>)
  { std::cout << "n::overloaded(wrapper<int>)" << std::endl; }
}

template<typename T> void try_it(T value) {
  overloaded(n::wrapper<T>{value});
}

namespace n {
  inline void overloaded(wrapper<C>)
  { std::cout << "n::overloaded(wrapper<C>)" << std::endl; }
}

这篇关于命名空间中的重载解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆