[英]boost optional and user-defined conversion
我無法為Item
類型編寫正確的用戶定義轉換。 這是我嘗試過的:
#include <iostream>
#include <boost/optional.hpp>
struct A
{
int x;
};
struct Item
{
boost::optional<int> x_;
Item(){}
Item(const A& s)
: x_(s.x)
{
}
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s->x = *x_;
}
return s;
}
};
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (const auto &i : items) {
if (i.x_) {
a.push_back(*static_cast<boost::optional<A>>(i)); // <- this line causes error
}
}
return a;
}
那就是我的用法:
int main() {
A a;
a.x = 3;
Item i(a);
auto v = getA({i});
return 0;
}
g++ -std=c++11
說:
In file included from /usr/include/boost/optional.hpp:15:0,
from test.cpp:2:
/usr/include/boost/optional/optional.hpp: In instantiation of ‘void boost::optional_detail::optional_base<T>::construct(const Expr&, const void*) [with Expr = Item; T = A]’:
/usr/include/boost/optional/optional.hpp:262:25: required from ‘boost::optional_detail::optional_base<T>::optional_base(const Expr&, const Expr*) [with Expr = Item; T = A]’
/usr/include/boost/optional/optional.hpp:559:78: required from ‘boost::optional<T>::optional(const Expr&) [with Expr = Item; T = A]’
test.cpp:30:55: required from here
/usr/include/boost/optional/optional.hpp:392:8: error: no matching function for call to ‘A::A(const Item&)’
new (m_storage.address()) internal_type(expr) ;
^
/usr/include/boost/optional/optional.hpp:392:8: note: candidates are:
test.cpp:3:8: note: A::A()
struct A
^
test.cpp:3:8: note: candidate expects 0 arguments, 1 provided
test.cpp:3:8: note: constexpr A::A(const A&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘const A&’
test.cpp:3:8: note: constexpr A::A(A&&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘A&&’
為什么它試圖找到A
結構的構造函數,而不是使用用戶定義的轉換操作符?
您可能會直接將我指向用戶定義的轉換頁的任何位置,因為我找不到任何原因。 例如,
在隱式轉換的第二階段調用用戶定義的轉換函數,該隱式轉換由零個或一個轉換構造函數或零個或一個用戶定義的轉換函數組成。
我認為直接表示如果未定義轉換構造函數,則將使用用戶定義的轉換函數。 我錯了嗎? 如果是的話,如何在不定義struct A
情況下實現用戶定義的轉換呢?
您的代碼有兩個問題。 您的optional
運算符永遠不會初始化boost::optional
。 如果不這樣做,則訪問成員是未定義的行為。 您要做的是:
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s = A{*x_};
}
return s;
}
第二個問題是您何時執行以下操作:
static_cast<boost::optional<A>>(i);
這等效於:
boost::optional<A> __tmp(i);
但事實證明, boost::optional
具有explicit
模板構造函數。 這將是您的轉換功能的首選。 您看到的錯誤是編譯沿着此工廠構造函數的路徑進行,而Item
不是這樣的工廠。
您可以直接使用boost::optional<A>
:
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (boost::optional<A> opt : items) {
if (opt) {
a.push_back(*opt);
}
}
return a;
}
或者,由於構造函數模板是explicit
,因此可以在非顯式上下文中使用轉換運算符:
boost::optional<A> opt = i;
a.push_back(*opt);
這樣做還有一個好處,就是易於閱讀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.