2017-06-27 13 views
0

gccがこのエラーを出力する理由を誰かに説明することはできますか?このコードでGCC vs variadicテンプレートコードのMSVCコンパイルエラー

/media/projects/src/libs/GUIElements/include/GUIElements/TemplatedFlagManager.h:195: 
error: ‘ClearQueue’ was not declared in this scope 
      ClearQueue<QueueType>(); 
      ^ 
/media/projects/src/libs/GUIElements/include/GUIElements/TemplatedFlagManager.h:35: error: 
    ‘typename std::enable_if<(I < sizeof... (Tp)), void>::type for_each(std::tuple<_Args2 ...>&, FuncT) 
    [with long unsigned int I = 1ul; FuncT = FlagNotifier<Args>::AddSubscriber(QSharedPointer<FlagSubscriber>) 
    [with Args = {SystemFlags::EAppFlags, SystemFlags::EQueueFlags, SystemFlags::EMessageFlags}]::<lambda(auto:2)>; 
    Tp = {QList<SystemFlags::EAppFlags>, QList<SystemFlags::EQueueFlags>, QList<SystemFlags::EMessageFlags>}; 
    typename std::enable_if<(I < sizeof... (Tp)), void>::type = void]’, 
    declared using local type ‘FlagNotifier<Args>::AddSubscriber(QSharedPointer<FlagSubscriber>) 
    [with Args = {SystemFlags::EAppFlags, SystemFlags::EQueueFlags, SystemFlags::EMessageFlags}]::<lambda(auto:2)>’, 
    is used but never defined [-fpermissive] 
    for_each(std::tuple<Tp...>& t, FuncT f) 
    ^

template <typename... Args> 
class FlagNotifier 
{ 
.... 

    void AddSubscriber(QSharedPointer<FlagSubscriber> sub) 
    { 
     for_each(flagQueues, [&](auto queue){ 
     using QueueType = typename decltype(queue)::value_type; 
     for(auto flag : queue) 
     { 
      auto& group = std::get<get_index<QueueType, Args...>::value>(flagGroups); 
      group[flag].push_back(sub); 
     } 

     ClearQueue<QueueType>(); 
     sub->ApplyState(); 
    }); 
    } 

    template <typename T> 
    void ClearQueue(){ 
     auto& flagQueue = std::get<get_index<T, Args...>::value>(this->flagQueues); 
     flagQueue.clear(); 
    } 
    std::tuple<QList<Args>...> flagQueues; 
    std::tuple<QHash<Args, QList<QSharedPointer<FlagSubscriber>>>...> flagGroups; 
} 

MSVCはそれに完全に罰金です。 「オートキューは」そうタイプを簡単に推論する必要がありますし、まだこのあいまいな警告...

P.S.実際にタプル

std::tuple<QList<Args>...> flagQueues; 

のメンバーであります

for_eachはこの質問から取得されます:stackoverflow.com/a/6894436/1143162

GET_INDEXここから:あなたはそれが依存としてそれを扱いたいのに対し、stackoverflow.com/a/18063608/1143162

+0

をコンパイルに失敗 '何をfor_each'されますか? ClearQueueの問題は、インスタンス化時にのみ視覚的なチェック内容であるように見えます(1パス対2パス必要)。 – Jarod42

+0

for_eachはここからタプル反復メカニズムです:https://stackoverflow.com/a/6894436/1143162 – Zeks

+0

とget_indexはここからです:https://stackoverflow.com/a/18063608/1143162 – Zeks

答えて

3

ClearQueue<QueueType>();が非依存名として扱われます。

this->template ClearQueue<QueueType>(); 

に変更

はあなたの問題を解決する必要があります。

エクストラtemplateは、式を正しく解析するために必要です。

2

今、質問に答える。 Jarod42は既に言及しましたは間違っていると私は説明しようとしますなぜ

FlagNotifierはテンプレートクラスです。メンバ関数ClearQueueを呼び出すときに、特定のコンテキストでは、メンバ関数または空き関数ClearQueue(あなたが持っていると仮定しましょう)への呼び出しである必要がある場合、コンパイラが不明瞭になることがあります。

のは、このシンプルなおもちゃの例を見てみましょう:

#include <iostream> 

template<typename T> 
struct B { 
    int f(); 
}; 

template<typename T> 
struct D : B<T> { 
    int g(); 
}; 

template<typename T> 
int D<T>::g() { 
    return f(); // error: should be ‘this->f()’ 
} 

int main() 
{ 
    return 0; 
} 

このはずないコンパイルが、私は、例えば、ない「foo」という機能を持っていないクラスBの特殊化を定義しているかもしれないということである理由

template<> 
struct B<int> { 
}; 

その後、次のコードが壊れになるだろう:

D<int> d; 
d.g(); 

そのため、C++標準では、このような状況ではthis->を明示的に使用する必要があります。

なぜ、Visual Studioに不平を言っていないのですか?この規則に関する規格に準拠していないためです。その理由は、このコンパイラは、C++標準のテンプレート特殊化規則が安定化されるずっと前から導入されていたため、後でMicrosoftは下位互換性を壊すのを嫌っていたからです。 Visual C++ 2017では、このルールを適用する特別なフラグ/許可を導入しました。他の多くのルールと同様に、詳細はhereを参照してください。

また、あなたがリンクダウンし、このおもちゃの例を見つけることができます。

関連する問題