簡體   English   中英

提高可選和用戶定義的轉換

[英]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.

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