c++ - 我如何制作一个允许所有左值引用、右值引用和 initializer_list 的模板化构造函数?

标签 c++ compiler-errors c++11 rvalue-reference perfect-forwarding

我正在尝试设计一个包含两个大序列 vector 的类。

std::vector<double> factory() {
    return std::vector<double>{1,2,3}; // it actually generates a large sequence of double
}

struct my_class {
    my_class(const std::vector<double>& x, const std::vector<double>& y)
     : m_x(x), m_y(y)
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

int main() {
    my_class c(factory(), factory());
    my_class c2(factory(), {0.5, 1, 1.5});
}

嗯,它工作得很好,但它没有使用 vector 的移动构造函数。所以我尝试更改构造函数以接受具有完美转发的 r 值引用。

struct my_class {
    template<typename X, typename Y>
    my_class(X&& x, Y&& y
             , typename std::enable_if<std::is_convertible<X, std::vector<double> >::value &&
                                       std::is_convertible<Y, std::vector<double> >::value>::type * = 0
            )
     : m_x(std::forward<X>(x)), m_y(std::forward<Y>(y))
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

现在我遇到了一个问题。当我尝试使用 initializer_list 构造实例时,出现了这样的错误。

$ g++ -W -Wall -std=gnu++0x a.cpp
a.cpp: In function ‘int main()’:
a.cpp:34:32: error: no matching function for call to ‘my_class::my_class(std::vector<double>, <brace-enclosed initializer list>)’
a.cpp:17:18: note: candidate is: my_class::my_class(const my_class&)

我认为 std::initializer_list<double>可能无法转换为 std::vector<double> ,但它实际上是可转换的,当我尝试不使用 enable_if 参数时,我遇到了同样的错误。我错过了什么吗?

最佳答案

首选成语是 to pass by value然后在成员初始值设定项列表中手动移动:

struct my_class {
    my_class(std::vector<double> x, std::vector<double> y)
     : m_x(std::move(x)), m_y(std::move(y))
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

这将适用于所有可能的参数并且相当快:

  • 如果您传递一个 vector 左值,该 vector 将被复制x,然后移动到m_x .
  • 如果您传递一个 vector 右值,该 vector 将移动x,然后再次移动到m_x.
  • 如果您传递初始化列表,x 将从该列表初始化,然后移至 m_x

另一种方法是完美转发,但这会使客户端更难知道他可能传递的内容:

struct my_class {
    template<typename T, typename U>
    my_class(T&& x, U&& y)
     : m_x(std::forward<T>(x)), m_y(std::forward<U>(y))
    { }

    std::vector<double> m_x;
    std::vector<double> m_y;
};

另外,我在 g++ 中收到了一堆警告,所以我不推荐它。只是为了完整性而提及它。

关于c++ - 我如何制作一个允许所有左值引用、右值引用和 initializer_list 的模板化构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8018878/

相关文章:

c++ - 从订购的容器中制作比较器

c++ - 为什么 C++11/14 中的 std::forward 没有 std::move_if_noexcept 对应项?

c++ - 从多个线程更新对应于 unordred_map 中不同现有键的值

c++ - 使用 std::initializer_list 作为成员变量

c++ - 从STL容器继承

c++ - 通过 stat() 函数传递字符串

java - 无法在 ArrayList 中找到符号

c++ - 可变参数模板未在 MSVC 中编译?

每行都有 Java Eclipse 错误

scala - 使用 Deadbolt 2 : overriding method getSubject in trait DeadboltHandler of type 玩框架