簡體   English   中英

在C ++ 11中使用auto和decltype

[英]Using auto and decltype in C++11

我正在嘗試學習當前接受的c ++ 11功能,而我遇到了auto和decltype的問題。 作為一個學習練習,我正在使用一些通用函數擴展std類列表。

template<class _Ty, class _Ax = allocator<_Ty>>
class FList : public std::list<_Ty, _Ax>
{
public:
    void iter(const function<void (_Ty)>& f)
    {
        for_each(begin(), end(), f);
    }

    auto map(const function<float (_Ty)>& f) -> FList<float>*
    {
        auto temp = new FList<float>();

        for (auto i = begin(); i != end(); i++)
            temp->push_back(f(*i));

        return temp;
    }
};

auto *ints = new FList<int>();
ints->push_back(2);
ints->iter([](int i) { cout << i; });

auto *floats = ints->map([](int i) { return (float)i; });
floats->iter([](float i) { cout << i; });

對於成員映射,我希望返回類型是通用的,具體取決於傳遞的函數返回的內容。 所以對於返回類型,我可以做這樣的事情。

auto map(const function<float (_Ty)>& f) -> FList<decltype(f(_Ty))>*

這還需要刪除函數模板中的float類型。

auto map(const function<auto (_Ty)>& f) -> FList<decltype(f(_Ty))>*

我可以使用模板類,但這使得實例的使用更加冗長,因為我必須指定返回類型。

template<class T> FList<T>* map(const function<T (_Ty)>& f)

總結我的問題,我試圖弄清楚如何在不使用模板類的情況下定義地圖,並且仍然在它返回的類型中使用它。

不鼓勵從std::list或其他std:: containers派生。

將您的操作編寫為自由函數,以便它們可以通過迭代器在任何標准容器上工作。

你的意思是“不使用模板功能定義地圖”?

您應該能夠使用std::functionresult_type成員類型來獲取它返回的類型。

此外,您無需指定該函數作為std::function傳遞。 您可以將其保持為任何類型,並讓編譯器加入所有類型。 您只需要std::function用於運行時多態性。

使用new創建原始堆分配對象並通過指針返回它們是soooo 1992! :)

你的iter函數與基於范圍的for循環基本相同。

但除此之外......你的意思是這樣嗎?

template <class TFunc>
auto map(const TFunc &f) -> FList<decltype(f(_Ty()))>*
{
    auto temp = new FList<decltype(f(_Ty()))>();

    for (auto i = begin(); i != end(); i++)
        temp->push_back(f(*i));

    return temp;
}

這將匹配任何可調用的東西,並將使用decltype找出函數的返回類型。

請注意,它要求_Ty是默認構造的。 您可以通過制造實例來解決這個問題:

template <class T>
T make_instance();

不需要實現,因為沒有生成調用它的代碼,因此鏈接器沒有什么可抱怨的(感謝dribeas指出這個!)

所以代碼現在變成:

FList<decltype(f(make_instance<_Ty>()))>*

或者,字面上,您可以通過引用_Ty實例調用函數f獲得的類型列表。

並且作為接受的免費獎勵,查找右值引用 - 這意味着您可以寫:

std::list<C> make_list_somehow()
{
    std::list<C> result;
    // blah...
    return result;
}

然后像這樣調用它:

std::list<C> l(make_list_somehow());

因為std :: list將有一個“移動構造函數”(就像復制構造函數一樣,但是當參數是臨時的時候選擇,就像這里一樣),它可以竊取返回值的內容,即與最佳swap相同。 所以沒有復制整個列表。 (這就是為什么C ++ 0x會使天真編寫的現有代碼運行得更快 - 許多流行但丑陋的性能技巧將變得過時)。

而且你可以通過使用unique_ptr免費為你自己的任何現有類獲得相同類型的東西,而無需編寫正確的移動構造函數。

std::unique_ptr<MyThing> myThing(make_my_thing_somehow());

您不能在函數參數中使用auto,因為您希望推導出參數的類型。 你使用模板。 看看: http//thenewcpp.wordpress.com/2011/10/18/the-keyword-auto/http://thenewcpp.wordpress.com/2011/10/25/decltype-and-declval/ 他們都解釋了如何使用auto和decltype。 他們應該為您提供有關如何使用它們的足夠信息。 特別是,關於make_instance的另一個答案可以通過declval更好地完成。

我認為Jarrah在他的回答中提出的觀點是,這些要點確實解釋了如何使用這些東西。 無論如何我會指出細節:

你不能這樣做,有兩件事是錯的:

auto map(const function<auto (_Ty)>& f) -> FList<decltype(f(_Ty))>*

auto不能用於函數參數。 如果您想要推導出函數的類型,那么您應該使用模板。 第二個是decltype采用表達式,而_Ty是一個類型。 以下是如何解決它:

template <typename Ret>
auto
map(const function<Ret (_Ty)>& f)
  -> FList<decltype(f(declval<_Ty>()))>
{}

這樣,創建一個類型的實例就沒有魔力。

暫無
暫無

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

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