簡體   English   中英

您如何在 C++ 概念中定義 emplace_back 和其他可變參數模板函數?

[英]How do you define emplace_back and other variadic template functions in a C++ concept?

我正在嘗試為允許 push_back/emplace_back 的標准庫容器定義 C++ 概念:

template <class ContainerType>
concept PushBackContainer = requires(ContainerType a)
{
    requires SequenceContainer<ContainerType>;
    { a.push_back(typename ContainerType::const_reference& v) };
    { a.push_back(typename ContainerType::value_type&& v) };
    // How do you define a variable templated function: 
    { template< class... Args > a.emplace_back(Args&&... args) };
}

我的問題是如何使用可變參數模板參數定義 emplace_back ? 我正在使用 Visual Studio 2019,但如果它不受支持,我會對正確的語法感興趣。

可能最值得做的就是a.emplace_back(); .

您的push_back要求也沒有正確的語法。 我想你想要:

template <class ContainerType>
concept PushBackContainer = requires(
    ContainerType& a,
    typename ContainerType::value_type const& cv,
    typename ContainerType::value_type& v)
{
    requires SequenceContainer<ContainerType>;
    a.push_back(cv);
    a.push_back(std::move(v));
    a.emplace_back();
};

需求不檢查函數簽名; 他們檢查表達式的有效性(無需實例化更多模板)。 如果我們有一個類:

class StrangeContainer {
public:
    using value_type = std::string;
    using const_reference = const value_type&;
private:
    struct ValueHolder {
        ValueHolder(const std::string& s) : value(s) {}
        ValueHolder(std::string&& s) : value(std::move(s)) {}
        std::string value;
    };
public:
    void push_back(ValueHolder);

    template <typename ... Args>
    void emplace_back(Args&&...);
};

然后忽略SequenceContainer要求, PushBackContainer<StrangeContainer>將是 true,並且它也將滿足與push_back相關的標准自己的要求。 它滿足技術要求,即使它有一些令人驚訝的效果,例如push_back("")

所以對於push_back ,我們實際上只是檢查它是否可以使用const左值和非const右值調用。 (標准實際上還要求可以使用非const左值和const右值調用它,這些情況與使用const左值調用時具有相同的行為。)

(如果你真的想測試一個確切的push_back簽名,你可以嘗試static_cast<void (ContainerType::*)(typename ContainerType::value_type&&)>(&ContainerType::push_back); - 但不推薦這樣做,因為成員函數命名空間std中的簽名不需要與所描述的完全相同,只需可以使用與所描述的聲明相同的參數調用。)

此外,標准容器類模板對其push_backemplace_back函數沒有任何限制。 具有push_back的模板的每個實例都聲明了兩個重載,無論類型是否可復制和/或可移動。 如果沒有,實際調用或以其他方式使用push_back函數將是一個錯誤,但它“存在”是為了需要表達式和 SFINAE 上下文。 同樣, emplace_back成員模板被聲明為接受任意數量的具有任何類型和值類別的參數,無論它們是否可以用作value_type構造函數參數。

因此,我們想要測試以找出容器是否有一個帶有本質上普通可變參數函數聲明的emplace_back需要表述為: 可以使用任意數量的參數調用emplace_back ,每個參數都有任何可能的類型,每個參數都可以是左值還是右值? 我認為沒有任何方法可以在 C++ 中真正回答這個問題,使用需要表達式、SFINAE 技巧或其他方式。 因此,我只會對某種emplace_back存在進行一個簡單的測試,而該測試也可能盡可能簡單:零參數。

您可以變得更emplace_back ,還可以測試一些其他情況: emplace_back是否接受不同數量的參數,最多達到某個固定的最大值? 它接受左值和右值參數嗎? 它是否接受虛擬struct類型的參數? 不是 MoveConstructible 的虛擬struct類型? constvolatileconst volatile類型? 以上所有可能的組合? 但是,由於您永遠不會涵蓋所有情況,與添加檢查所需的工作量、復雜性和維護相比,像這樣的每個部分增強真正提供了多少價值?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM