2017-05-05 65 views
2
#include <type_traits> 
#include <functional> 

struct Chains 
{}; 

struct Stages 
{ 

    Chains mutating_chains; 

    Chains sideffect_chains; 

    Chains write_chains; 

    void forall_chains(const std::function<void(Chains & chain)> & fun) 
    { 
     forall_chains(*this, fun); 
    } 

    void forall_chains(
     const std::function<void(const Chains & chain)> & fun) const 
    { 
     forall_chains(*this, fun); 
    } 

    template <typename Self> 
    static void forall_chains(
     Self & self, 
     const std::function<void(decltype(self.mutating_chains) & chain)> & fun) 
    { 
     fun(self.mutating_chains); 
     fun(self.sideffect_chains); 
     fun(self.write_chains); 
    } 
}; 

顯然有一些我無法理解的decltype。因爲根據編譯器拋出的錯誤消息,Self被推斷爲const Stages,所以爲什麼self.member不會被推斷爲const成員?還有如何使它正常工作,推導const對象的const成員?我在表達式decltype((self.mutating_chains))中添加了括號,並且通過了編譯,但我不確定這是否是正確的操作。decltype不會推斷const對象的常量成員

f.cpp: In instantiation of ‘static void Stages::forall_chains(Self&, const std::function<void(decltype (self.mutating_chains)&)>&) [with Self = const Stages; decltype (self.mutating_chains) = Chains]’: 
f.cpp:150:33: required from here 
f.cpp:158:33: error: no match for call to ‘(const std::function<void(Chains&)>) (const Chains&)’ 
     fun(self.mutating_chains); 
+0

你可以把代碼放在一個f.cpp中並編譯它,它會正好拋出這個錯誤信息 – mkmostafa

回答

4

我加括號來表達decltype((self.mutating_chains))並通過編譯,但我不知道這是做正確的事。

是的,這是在這種情況下正確的做法。簡而言之,decltype(x)會給出聲明的類型x,它不依賴於表達式的值類別。

對於左值表達式T類型的xdecltype((x))代替產生T&,而你的情況得到const限定符施加正確。

您可以在cppreference page for decltype(...)上找到更爲正式的(和準確的)解釋。


順便說一句,請考慮通過模板參數而不是std::function通過你的回調。後者不是一個零成本的抽象 - 它是一個使用類型擦除的重量級包裝,它的使用應該被最小化。

template <typename Self, typename F> 
static void forall_chains(Self& self, F&& fun){ /* ... */ } 

我寫了一篇關於這個問題的文章:passing functions to functions

+1

謝謝你的回答和獎金建議:) – mkmostafa

4

是的的確的。 decltype具有用於decltype(self.mutating_chains)(重點煤礦)一種特殊情況:

如果參數是一個括號的ID-表達或的加括號的類的成員訪問表達式,然後decltype產生由該表達指定的實體的類型。

因此,您將獲得與self.mutating_chains已聲明的實際類型,即Chains

當您添加括號,則回落到一般情況下,這實際上計算表達式,這在const Self的情況下const Chains &預期的類型:

如果參數是其他任何b)如果表達式的值類別是左值,則decltype產生T&;如果表達式的值類別是左值,則decltype產生T&;如果表達式的值類別是左值,則decltype產生T&;如果表達式的值類別是左值,則decltype產生T&;
c)[...]