c++ - 将从元组派生的对象放入 C++ 中的 vector 中

标签 c++ inheritance vector c++11 tuples

我想创建一个包含 3 个值的结构:一个字符串和两个整数。该字符串是强制性的,但其中一个(或两个)整数是可选的,如果未指定则可以默认为 -1。

但是,与其使用结构,不如尝试使用 std::tuple。为了合并两个整数的可选性,我设置了一个继承自 std::tuple 的“Trio”类,如下所示:

#include <string>
#include <tuple>

class Trio : public std::tuple<std::string, int, int>
{
    public:

    explicit Trio(std::string const & name, int val1 = -1, int val2 = -1)
    :
        tuple(name, val1, val2)
    {
    }
};

然后我通过将一些 Trio 对象插入 std::vector 来测试 Trio 类:

#include <vector>
int main(void)
{
    std::vector<Trio> trios;

    Trio trio("trio1", 1, 1);
    trios.push_back(trio);

    return 0;
}

它在 Visual Studio 2010 中给我以下错误:

>c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple(127):
    error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const
    std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1
    from 'const Trio' to 'const std::basic_string<_Elem,_Traits,_Ax> &'
 with
 [
     _Elem=char,
     _Traits=std::char_traits<char>,
     _Ax=std::allocator<char>
 ]
 Reason: cannot convert from 'const Trio' to 'const
 std::basic_string<_Elem,_Traits,_Ax>'
 with
 [
     _Elem=char,
     _Traits=std::char_traits<char>,
     _Ax=std::allocator<char>
 ]
 No user-defined-conversion operator available that can perform
 this conversion, or the operator cannot be called

有人明白我在这里做错了什么吗?有什么明显的东西我只是没有看到吗?我是否在严重滥用 std::tuple 的用法?

谢谢,

亚伦

最佳答案

这是 VC10 的一个错误

VC10 提示是因为您的类似乎没有复制构造函数。因此,为了复制 Trio 类型的值,它会尝试将它们转换为 string ,这是你提供的构造函数接受的(其他参数可以被赋予默认值)。这就是您提示的错误:

cannot convert parameter 1 from 'const Trio' to 'const std::basic_string<_Elem,_Traits,_Ax> &'

您可以通过显式添加复制构造函数并观察错误消失来验证这确实是正在发生的事情:

Trio(Trio const& t) { *this = t; }

现在 VC10 很满意,因为它看到了一个复制构造函数,并且代码可以正常编译。

然而,当用户没有显式提供复制构造函数时,您的编译器应该隐式生成一个。根据 C++11 标准的第 12.8/7 段:

If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). [...]

Trio没有显式声明任何复制构造函数。根据 C++11 标准的第 12.8/2 段,事实上:

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (8.3.6)

因此,您显式提供的构造函数不是复制构造函数并且应该禁止复制构造函数的隐式生成。

VC10 可能会将您提供的构造函数误解为复制构造函数,因此不会隐式生成一个。但是,由于上面所写的内容,此行为是不正确的,属于错误。(*)

附带说明一下,您的代码在 Clang 3.2、GCC 4.7.2 和 ICC 13.0.1 上编译良好。

更新:

我尝试使用不涉及 std::tuple<> 的更简单的数据结构来重现该问题,我失败了。因此,该错误不仅仅是因为您的构造函数被 VC10 误解为显式复制构造函数这一事实。然而,这并不能改变 VC10 行为不正确的事实。

关于c++ - 将从元组派生的对象放入 C++ 中的 vector 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14987847/

相关文章:

iphone - 带有工厂方法的 Objective C 类继承

python - 强制唯一与模型继承一起

c++ - 如何按值从 vector 中删除元素但仅删除该值的单个实例?

c++ - 如何将 const 指针的 vector const_cast 转换为非常量指针的 vector ?

c++ - 如何为已弃用的英特尔 IPP API 找到替代 API?

java - 实例是否应该使用 setter/getter 来访问它们自己的私有(private)数据成员?

.net - 有没有办法找到哪些 .NET 类实现了某个接口(interface)?

c++ - 关于 vector 的困惑

C++ 线程安全延迟加载

c++ - 多态性:成员访问和getter给出不同的结果