c++ - 将 operator!= 实现为自由函数的类外模板的正确方法

标签 c++ templates c++11 linker-errors non-member-functions

我在 map.hpp 文件中有一个内部类模板:

template<typename Key_T, typename Mapped_T>
class Map {
    // public members of Map ...

    class Iterator {
        //public members of Iterator ...

        friend bool operator!=(const Iterator &i, const Iterator &j) {
            return (i.link != j.link);  
        }

        // private members of iterator ...
        Node * link;
    };
};
#include "map.hxx"   //implementation file for member methods is separate

main.cpp 中,我调用了以下内容,到目前为止一切正常:

Map<int, int> x;
// bunch of insertions ...
for (auto it = x.begin; it != x.end(); ++it) {
    // Do something with it ...   
}

但是,我想将友元函数从 map.hpp 文件中移到包含其他实现的 map.hxx 文件中。

问:是否可以将自由函数移动到 .hxx 文件,如何移动?

我厌倦了在 Iterator 类中将函数声明为友元,并在实现文件中执行了以下操作:

template<typename Key_T, typename Mapped_T>
bool operator!=(const typename Map<Key_T, Mapped_T>::Iterator & i,
                const typename Map<Key_T, Mapped_T>::Iterator & j) {
    return (i.link != j.link);
}

但是失败了:

$clang++ -std=c++11 -stdlib=libc++ -Wall -Wextra -g main.cpp 

Undefined symbols for architecture x86_64:
  "shiraz::operator!=(shiraz::Map<int, int>::Iterator const&, shiraz::Map<int, int>::Iterator const&)", referenced from:
      _main in main-3oCRAm.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

谢谢!

最佳答案

A friend没有相应匹配的声明会将新函数注入(inject)封闭的命名空间。这个函数只能通过ADL找到

做你想做的最简单的方法是在iterator中留下一个 stub 实现。类,并将其转发到外部的“真实”功能。这保留了很好的仅 ADL 查找 != ,轻松解决了一些棘手的过载问题。辅助函数可以简单地是 template<class Iterator>并且更正常地成为 friend 并且有一个狭窄的实现,并且不是通过 ADL 而是通过完全限定的查找找到的。或者它可以是封闭映射的静态成员函数。

template<typename Key_T, typename Mapped_T>
class Map {
  class Iterator;
  static bool it_equal( Iterator const&, Iterator const& );
  class Iterator {
    friend class Map;
    friend bool operator!=(const Iterator &i, const Iterator &j) {
      return !Map::it_equal(i,j);
    }
    friend bool operator==(const Iterator &i, const Iterator &j) {
      return Map::it_equal(i,j);
    }
    Node * link;
  };
};

现在您的 .hxx简单地实现 bool Map<blah>::it_equal(blah)你就完成了。

关于c++ - 将 operator!= 实现为自由函数的类外模板的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29111961/

相关文章:

c++ - 明确停止后期绑定(bind)

c++ - 为右值参数隐式生成函数重载?

java - 为什么 Velocity 不显示 <div >'s that should be displayed as "显示 : flex;"correctly?

c++ - 获取模板中的函数返回类型

c# - 从非托管 C/C++ 代码调用 C# .NET 方法

c++ - 暂时删除互斥句柄

c++ - 是否可以在 C++ 中有一个指向模板函数的函数指针?

c++ - 如何在 std::vector 中生成对象而不复制?

c++ - 在不锁定的情况下在线程之间复制 std::vector

c++ - 与成员函数中的 std::move(*this) 的行为差异