[英]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_back
或emplace_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
類型? const
、 volatile
和const volatile
類型? 以上所有可能的組合? 但是,由於您永遠不會涵蓋所有情況,與添加檢查所需的工作量、復雜性和維護相比,像這樣的每個部分增強真正提供了多少價值?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.