Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.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++ - Fatal编程技术网

C++ 在类设计的外部命名空间中查找重载运算符

C++ 在类设计的外部命名空间中查找重载运算符,c++,C++,如何让名称空间中的包装类知道在外部/全局名称空间中,它包装的对象可能存在重载运算符? 注意:我听说过ADL或Koenig查找,但我遇到了一个真正的问题 真正的设计问题 我想设计一个只有标题的库。假设我将所有内容都放在命名空间my中。与此问题相关的部分可以简化为类似于模板包装的item // my.hpp #include <iostream> namespace my { template<typename T> struct item {

如何让名称空间中的包装类知道在外部/全局名称空间中,它包装的对象可能存在重载运算符?

注意:我听说过ADL或Koenig查找,但我遇到了一个真正的问题

真正的设计问题

我想设计一个只有标题的库。假设我将所有内容都放在命名空间
my
中。与此问题相关的部分可以简化为类似于模板包装的
item

// my.hpp

#include <iostream>

namespace my
{
    template<typename T>
    struct item
    {
        T thing;
        item(T t) : thing(t) {}
    };

    template<typename T>
    std::ostream & operator<<(std::ostream & os, const item<T> & it)
    {
        os << it.thing;
        return os;
    }
}

user.cpp
开始时,一切都会很好,
g++user.cpp
将按预期编译

但是,如果用户更改了订单并将

#include "my.hpp"
#include "user.hpp"
编译器将生成一个错误,说明

my.hpp: In function 'std::ostream& my::operator<<(std::ostream&, const my::item<T>&)':
my.hpp:15:23: error: '::operator<<' has not been declared
在阅读了一篇关于meta的文章,并根据评论中的建议,我在我自己的问题中移动了一些“更新”,并将它们作为自我回答正式发布。我这样做是希望这将有助于将来遇到同样问题的人。谢谢大家!

正如@xskxzr在评论中正确指出的,用户代码中存在一些不好的地方。具体来说,

声明其参数均为
std
实体的函数/操作是不好的,因为您无法将此类声明添加到std中以利用ADL

在这种情况下,问题在于用户,而不是设计者

现在,如果用户进行了更改

// user.hpp

#include <iostream>
#include <vector>

// CHANGE: (privately) inherit from std::vector<double>, rather than overload directly

struct DoubleVector : private std::vector<double>
{
    using std::vector<double>::vector;

    friend
    std::ostream & operator<<(std::ostream &, const DoubleVector &);
};

std::ostream & operator<<(std::ostream &, const DoubleVector &);
//user.hpp
#包括
#包括
//CHANGE:(私下)从std::vector继承,而不是直接重载
struct DoubleVector:private std::vector
{
使用std::vector::vector;
朋友

std::ostream&operator此示例的可能副本表明,声明参数均为std实体的函数/操作是不好的,因为您无法将此类声明添加到std中以利用ADL。在我看来,避免此类函数/操作是用户的责任。但是,他可以声明新的
Vector
类(可以继承
std::vector
)并在
vector
@xskxzr上声明操作。谢谢!经过再三考虑,我完全明白了。你需要填写答案。@darune谢谢。就这么做了。
#include "my.hpp"
#include "user.hpp"
my.hpp: In function 'std::ostream& my::operator<<(std::ostream&, const my::item<T>&)':
my.hpp:15:23: error: '::operator<<' has not been declared
g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0
// user.hpp

#include <iostream>
#include <vector>

// CHANGE: (privately) inherit from std::vector<double>, rather than overload directly

struct DoubleVector : private std::vector<double>
{
    using std::vector<double>::vector;

    friend
    std::ostream & operator<<(std::ostream &, const DoubleVector &);
};

std::ostream & operator<<(std::ostream &, const DoubleVector &);
// user.cpp

#include "my.hpp"
#include "user.hpp"

#include <iostream>
#include <vector>

// CHANGE: use a user-defined DoubleVector class

std::ostream & operator<<(std::ostream & os, const DoubleVector & c)
{
    for (const auto & e : c)
        os << e << " | ";
    return os;
}

int main()
{
    DoubleVector vec = {3.14, 2.83};
    std::cout << my::item<DoubleVector>(vec);
}