[英]Initialize a tuple of non-copyable and non-movable classes
考慮具有唯一自定義構造函數的類A:
class A
{
public:
A(float) {}
private:
A() = delete;
A(const A&) = delete;
A(A&&) = delete;
};
還有另一個類B,其中包含A的元組(為簡單起見,請使其成為唯一的元組成員):
class B
{
public:
B() : ta(0.0f) {} // ta initialization OK
private:
std::tuple<A> ta;
};
現在我們可以聲明B的對象,並且可以正常工作:
B b;
但是,如果A
的構造函數具有多個參數,該如何做呢?
class A
{
public:
A(float, int) {}
private:
A() = delete;
A(const A&) = delete;
A(A&&) = delete;
};
class B
{
public:
// B() : ta(0.0f, 1) {} // Compilation errors
// B() : ta({0.0f, 1}) {} // Compilation errors
// B() : ta{0.0f, 1} {} // Compilation errors
// B() : ta(A(0.0f, 1)) {} // No constructor to copy or move A
private:
std::tuple<A> ta;
};
B b;
std::make_tuple
, std::forward_as_tuple
和其他類似的方法都不能解決問題,因為默認情況下, A
復制,構造函數和移動構造器均被禁用。
std::tuple
很少有用於就地構建其成員的設施。 通常,初始化tuple
是通過從其組件對象復制/移動。
它確實允許將構造函數參數隱式轉換為它們各自的參數。 但這只是參數和tuple
成員之間的1:1關系。 構造函數參數和tuple
成員之間沒有多對一的關系。
您可以允許從tuple
本身隱式構造您的類型:
class A
{
public:
A(float, int) {}
A(const std::tuple<float, int> &tpl)
: A(std::get<0>(tpl), std::get<1>(tpl)) {}
private:
A() = delete;
A(const A&) = delete;
A(A&&) = delete;
};
因此,您可以像這樣構造一個tuple
:
class B
{
public:
B() : ta(std::tuple<float, int>(0.0f, 1)) {}
private:
std::tuple<A> ta;
};
如果要使用更深入的元編程,則可能仍可以創建一組構造函數,以允許從其類型與任何可用構造函數匹配的tuple
構造類型:
class A
{
public:
A(float, int) {}
template<typename ...Args>
A(const std::tuple<Args...> &args) : A(args, std::index_sequence_for<Args...>{}) {}
private:
A() = delete;
A(const A&) = delete;
A(A&&) = delete;
template<typename ...Args, std::size_t ...Is>
A(const std::tuple<Args...> &args, std::index_sequence<Is...>)
: A(std::get<Is>(args)...) {}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.