使用 std::map 和自定义 class 作为其值的编译器错误 C2664
Compiler error C2664 using std::map and custom class as its value
我已就此问题进行了大量搜索,但 none 的答案很有帮助。
我的设置
- Visual Studio 2017
- Windows 10
我有一个很大的代码库,其中一个 class 栏
// Bar.h
class Bar {
public:
Bar();
~Bar();
public:
... // a long list of other methods.
private:
std::map<std::string, Foo> m_foos;
};
然后在实施中
// Bar.cpp
Bar::Bar() {
m_foos.insert(std::make_pair(std::string("id"), Foo())); // Error 1
m_foos.insert({std::string("id"), Foo()}); // Error 2
m_foos.insert(std::pair<std::string, Foo>(std::string("id"), Foo())); // Error 3
}
尝试编译上面的代码给我:
错误 1
error C2664: 'std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>> std::_Tree<std::_Tmap_traits<_Kty,Foo,_Pr,_Alloc,false>>::insert(std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>,const std::pair<const _Kty,Foo> &)': cannot convert argument 1 from 'std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,Foo>' to 'std::pair<const _Kty,_Ty> &&'
错误 2
error C2664: 'std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>> std::_Tree<std::_Tmap_traits<_Kty,Foo,_Pr,_Alloc,false>>::insert(std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>,const std::pair<const _Kty,Foo> &)': cannot convert argument 1 from 'initializer list' to 'std::pair<const _Kty,_Ty> &&'
错误 3
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,Foo>'
但是,使用相同的设置和编译器,以下大大简化的代码可以成功编译:
#include "pch.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
class Foo {
public:
Foo() { mi = 1; }
~Foo() {}
private:
int mi;
};
class MyFoo : public Foo {
public:
MyFoo() :Foo() {
mj = 2;
mk = nullptr;
}
~MyFoo() {}
private:
int mj;
int* mk;
};
class YourFoo : public Foo {
public:
YourFoo() :Foo() { mj = 2; }
~YourFoo() {}
private:
int mj;
};
int main()
{
std::map<int, Foo> yourmap;
yourmap.insert(std::make_pair(3, Foo()));
yourmap.insert({ 4, Foo() });
yourmap.insert(std::pair<int, Foo>(5, Foo()));
}
我哪里错了?
更新
所以我终于可以重现它了。这是因为有问题的 class 层次结构删除了它们的复制构造函数和 operator =
.
修改后的例子可以重现错误。
#include "pch.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
class Foo {
public:
Foo() { mi = 1; }
~Foo() {}
// NO COPIES.
Foo(const Foo &) = delete;
Foo& operator = (const Foo &) = delete;
private:
int mi;
};
class MyFoo : public Foo {
public:
MyFoo() :Foo() {
mj = 2;
mk = nullptr;
}
~MyFoo() {}
// NO COPIES.
MyFoo(const MyFoo &) = delete;
MyFoo& operator = (const MyFoo &) = delete;
private:
int mj;
int* mk;
};
class YourFoo : public Foo {
public:
YourFoo() :Foo() { mj = 2; }
~YourFoo() {}
// NO COPIES.
YourFoo(const YourFoo &) = delete;
YourFoo& operator = (const YourFoo &) = delete;
private:
int mj;
};
int main()
{
std::map<int, Foo> yourmap;
yourmap.insert(std::make_pair(3, Foo()));
yourmap.insert({ 4, Foo() });
yourmap.insert(std::pair<int, Foo>(5, Foo()));
}
所以我猜问题是 std::map
必须将元素复制到它的内存中 space。然后它只是碰到没有复制构造函数的 classes 并抱怨。但是错误消息是如此具有误导性,以至于我无法弄清楚。实际的 class 层次结构非常庞大,所以我没有看到那些被删除的部分。我猜有人不希望这些东西被复制。
如果有人可以在我的问题开头指导如何破译编译器错误消息,以便我可以更好地了解在哪里查看,将不胜感激!
#include "pch.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
class Foo {
public:
Foo() { mi = 1; }
~Foo() {}
// NO COPIES.
Foo(const Foo &) = delete;
Foo& operator = (const Foo &) = delete;
private:
int mi;
};
class MyFoo : public Foo {
public:
MyFoo() :Foo() {
mj = 2;
mk = nullptr;
}
~MyFoo() {}
// NO COPIES.
MyFoo(const MyFoo &) = delete;
MyFoo& operator = (const MyFoo &) = delete;
private:
int mj;
int* mk;
};
class YourFoo : public Foo {
public:
YourFoo() :Foo() { mj = 2; }
~YourFoo() {}
// NO COPIES.
YourFoo(const YourFoo &) = delete;
YourFoo& operator = (const YourFoo &) = delete;
private:
int mj;
};
int main()
{
std::map<int, std::shared_ptr<Foo> > objects;
objects.insert(std::pair<int, std::shared_ptr<Foo> >(0, new Foo()));
}
我在 Visual Studio Community 2017 上构建这个程序没有任何问题:
#include "pch.h"
#include <iostream>
#include <map>
class Foo {
public:
Foo();
};
Foo::Foo() {
std::cout << "Foo is being constructed\n";
}
class Bar {
public:
Bar();
~Bar();
private:
std::map<std::string, Foo> m_foos;
};
Bar::Bar() {
m_foos.insert(std::make_pair(std::string("id"), Foo()));
m_foos.insert({ std::string("id"), Foo() });
m_foos.insert(std::pair<std::string, Foo>(std::string("id"), Foo()));
}
Bar::~Bar() {
std::cout << "Destructing bar\n";
}
int main()
{
Bar bar = Bar();
std::cout << "Hello World!\n";
}
控制台上的程序输出:
C:\Users\me\source\repos\SO0\Debug>SO0.exe
Foo is being constructed
Foo is being constructed
Foo is being constructed
Hello World!
Destructing bar
没有可用复制构造函数/复制赋值的 类 实例仍然可以在 std::map
中使用,使用一些特殊技巧:
- emplace 而不是 insert(就地构建映射条目)
- 使用
std::piecewise_construct
.
有关 cppreference.com 的更多信息:std::map::emplace
应用于OP示例代码:
#include <iostream>
#include <map>
#include <string>
class Foo {
public:
Foo(): mi("1") { }
~Foo() = default;
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
private:
std::string mi;
};
std::ostream& operator<<(std::ostream &out, const Foo &foo)
{
return out << "Foo()";
}
int main()
{
std::map<std::string, Foo> yourmap;
#if 0 // WON'T COMPILE due to deleted Foo::Foo(const Foo&):
yourmap.insert(std::make_pair("3", Foo()));
yourmap.insert({ "4", Foo() });
yourmap.insert(std::pair<std::string, Foo>("5", Foo()));
#endif // 0
yourmap.emplace(std::piecewise_construct,
std::forward_as_tuple("3"), // std::string("3")
std::forward_as_tuple()); // Foo()
// check result
for (auto &entry : yourmap) {
std::cout << '"' << entry.first << "\": " << entry.second << '\n';
}
}
输出:
"3": Foo()
我已就此问题进行了大量搜索,但 none 的答案很有帮助。
我的设置
- Visual Studio 2017
- Windows 10
我有一个很大的代码库,其中一个 class 栏
// Bar.h
class Bar {
public:
Bar();
~Bar();
public:
... // a long list of other methods.
private:
std::map<std::string, Foo> m_foos;
};
然后在实施中
// Bar.cpp
Bar::Bar() {
m_foos.insert(std::make_pair(std::string("id"), Foo())); // Error 1
m_foos.insert({std::string("id"), Foo()}); // Error 2
m_foos.insert(std::pair<std::string, Foo>(std::string("id"), Foo())); // Error 3
}
尝试编译上面的代码给我:
错误 1
error C2664: 'std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>> std::_Tree<std::_Tmap_traits<_Kty,Foo,_Pr,_Alloc,false>>::insert(std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>,const std::pair<const _Kty,Foo> &)': cannot convert argument 1 from 'std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,Foo>' to 'std::pair<const _Kty,_Ty> &&'
错误 2
error C2664: 'std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>> std::_Tree<std::_Tmap_traits<_Kty,Foo,_Pr,_Alloc,false>>::insert(std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>,const std::pair<const _Kty,Foo> &)': cannot convert argument 1 from 'initializer list' to 'std::pair<const _Kty,_Ty> &&'
错误 3
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,Foo>'
但是,使用相同的设置和编译器,以下大大简化的代码可以成功编译:
#include "pch.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
class Foo {
public:
Foo() { mi = 1; }
~Foo() {}
private:
int mi;
};
class MyFoo : public Foo {
public:
MyFoo() :Foo() {
mj = 2;
mk = nullptr;
}
~MyFoo() {}
private:
int mj;
int* mk;
};
class YourFoo : public Foo {
public:
YourFoo() :Foo() { mj = 2; }
~YourFoo() {}
private:
int mj;
};
int main()
{
std::map<int, Foo> yourmap;
yourmap.insert(std::make_pair(3, Foo()));
yourmap.insert({ 4, Foo() });
yourmap.insert(std::pair<int, Foo>(5, Foo()));
}
我哪里错了?
更新
所以我终于可以重现它了。这是因为有问题的 class 层次结构删除了它们的复制构造函数和 operator =
.
修改后的例子可以重现错误。
#include "pch.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
class Foo {
public:
Foo() { mi = 1; }
~Foo() {}
// NO COPIES.
Foo(const Foo &) = delete;
Foo& operator = (const Foo &) = delete;
private:
int mi;
};
class MyFoo : public Foo {
public:
MyFoo() :Foo() {
mj = 2;
mk = nullptr;
}
~MyFoo() {}
// NO COPIES.
MyFoo(const MyFoo &) = delete;
MyFoo& operator = (const MyFoo &) = delete;
private:
int mj;
int* mk;
};
class YourFoo : public Foo {
public:
YourFoo() :Foo() { mj = 2; }
~YourFoo() {}
// NO COPIES.
YourFoo(const YourFoo &) = delete;
YourFoo& operator = (const YourFoo &) = delete;
private:
int mj;
};
int main()
{
std::map<int, Foo> yourmap;
yourmap.insert(std::make_pair(3, Foo()));
yourmap.insert({ 4, Foo() });
yourmap.insert(std::pair<int, Foo>(5, Foo()));
}
所以我猜问题是 std::map
必须将元素复制到它的内存中 space。然后它只是碰到没有复制构造函数的 classes 并抱怨。但是错误消息是如此具有误导性,以至于我无法弄清楚。实际的 class 层次结构非常庞大,所以我没有看到那些被删除的部分。我猜有人不希望这些东西被复制。
如果有人可以在我的问题开头指导如何破译编译器错误消息,以便我可以更好地了解在哪里查看,将不胜感激!
#include "pch.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
class Foo {
public:
Foo() { mi = 1; }
~Foo() {}
// NO COPIES.
Foo(const Foo &) = delete;
Foo& operator = (const Foo &) = delete;
private:
int mi;
};
class MyFoo : public Foo {
public:
MyFoo() :Foo() {
mj = 2;
mk = nullptr;
}
~MyFoo() {}
// NO COPIES.
MyFoo(const MyFoo &) = delete;
MyFoo& operator = (const MyFoo &) = delete;
private:
int mj;
int* mk;
};
class YourFoo : public Foo {
public:
YourFoo() :Foo() { mj = 2; }
~YourFoo() {}
// NO COPIES.
YourFoo(const YourFoo &) = delete;
YourFoo& operator = (const YourFoo &) = delete;
private:
int mj;
};
int main()
{
std::map<int, std::shared_ptr<Foo> > objects;
objects.insert(std::pair<int, std::shared_ptr<Foo> >(0, new Foo()));
}
我在 Visual Studio Community 2017 上构建这个程序没有任何问题:
#include "pch.h"
#include <iostream>
#include <map>
class Foo {
public:
Foo();
};
Foo::Foo() {
std::cout << "Foo is being constructed\n";
}
class Bar {
public:
Bar();
~Bar();
private:
std::map<std::string, Foo> m_foos;
};
Bar::Bar() {
m_foos.insert(std::make_pair(std::string("id"), Foo()));
m_foos.insert({ std::string("id"), Foo() });
m_foos.insert(std::pair<std::string, Foo>(std::string("id"), Foo()));
}
Bar::~Bar() {
std::cout << "Destructing bar\n";
}
int main()
{
Bar bar = Bar();
std::cout << "Hello World!\n";
}
控制台上的程序输出:
C:\Users\me\source\repos\SO0\Debug>SO0.exe
Foo is being constructed
Foo is being constructed
Foo is being constructed
Hello World!
Destructing bar
没有可用复制构造函数/复制赋值的 类 实例仍然可以在 std::map
中使用,使用一些特殊技巧:
- emplace 而不是 insert(就地构建映射条目)
- 使用
std::piecewise_construct
.
有关 cppreference.com 的更多信息:std::map::emplace
应用于OP示例代码:
#include <iostream>
#include <map>
#include <string>
class Foo {
public:
Foo(): mi("1") { }
~Foo() = default;
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
private:
std::string mi;
};
std::ostream& operator<<(std::ostream &out, const Foo &foo)
{
return out << "Foo()";
}
int main()
{
std::map<std::string, Foo> yourmap;
#if 0 // WON'T COMPILE due to deleted Foo::Foo(const Foo&):
yourmap.insert(std::make_pair("3", Foo()));
yourmap.insert({ "4", Foo() });
yourmap.insert(std::pair<std::string, Foo>("5", Foo()));
#endif // 0
yourmap.emplace(std::piecewise_construct,
std::forward_as_tuple("3"), // std::string("3")
std::forward_as_tuple()); // Foo()
// check result
for (auto &entry : yourmap) {
std::cout << '"' << entry.first << "\": " << entry.second << '\n';
}
}
输出:
"3": Foo()