我有一个std::filesystem::directory_entry
从 directory_iterator 打印的项目。另一方面,我有一个完全独立的类重载std::ostream& operator<<
,它有一个模板化的构造函数,它初始化一个std::variant
成员。
#include <variant>
#include <iostream>
#include <filesystem>
typedef std::variant<long, std::string> VarType;
class Var {
VarType _value;
public:
template<typename T>
Var(T value) : _value{value} {
}
};
std::ostream& operator<< (std::ostream& stream, const Var&) {
return stream;
}
int main() {
std::cout << std::filesystem::directory_entry() << "\n";//tigger compling error
return 0;
}
编译失败:
main.cpp: In instantiation of ‘Var::Var(T) [with T =
std::filesystem::__cxx11::directory_entry]’: main.cpp:25:49:
required from here main.cpp:11:30: error: no matching function for
call to ‘std::variant<long int, double,
std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >::variant(<brace-enclosed initializer list>)’
Var(T value) : _value{value} {
... several pages of output ...
它似乎在将其发送到 之前尝试包装directory_entry
到,但我不确定。Var
cout
您能否解释一下实际发生了什么以及为什么代码是错误的?
我四处测试。对于这个问题,无论我投入什么似乎都可以variant
,即使是单个变体也有问题。这个
#include <variant>
#include <iostream>
#include <filesystem>
typedef std::variant<long, std::string> VarType;
class Var {
VarType _value;
public:
template<typename T>
Var(T value) : _value{value} {
}
};
std::ostream& operator<< (std::ostream& stream, const VarType&) {
return stream;
}
int main() {
std::cout << std::filesystem::directory_entry() << "\n";
return 0;
}
工作正常。如果我将_value
初始化移动到 c-tor 主体编译失败并出现相同的逻辑错误,但对于operator=
,至少它是一致的。显然它适用于非模板化的 c-tor。
如果我将 的实现ostream& operator<<
移到一个单独的单元中并将其定义为 的朋友Var
,则编译通过(这是一种合适的解决方法,但不应该operator<<
可以访问类的私有)。但是,如果我只是分开而不交朋友,它就失败了。
主.cpp:
#include "var.hpp"
#include <iostream>
#include <filesystem>
int main() {
std::cout << std::filesystem::directory_entry() << "\n";
std::cout << Var(1l) << "\n";
return 0;
}
var.hpp:
#include <variant>
#include <ostream>
typedef std::variant<long, std::string> VarType;
class Var {
VarType _value;
public:
template<typename T>
Var(T value) : _value{value} {
}
friend std::ostream& operator<< (std::ostream& stream, const Var&); //works
};
//std::ostream& operator<< (std::ostream& stream, const Var&); //instead above does not works
var.cpp:
#include "var.hpp"
std::ostream& operator<< (std::ostream& stream, const Var&) {
return stream;
}
这让我完全迷失了。假设它尝试Var
在这里调用 c-tor<<
应该没有区别。
为什么这样的改变很重要?
我用 g++8.4 构建(g++ -std=c++17 main.cpp var.cpp -lstdc++fs
我也尝试了 clang7.0 并获得了类似的结果)。