2016-01-27 3 views
5

以下は私が見ている問題を完全に示すプログラムです。C++ 14 auto lambdaはObj <std :: tuple <void>>を受け入れることができますが、テンプレート関数はできません。

まず、他のタイプのグループを使用して定義されたオブジェクトから始めます。グループを管理するためにstd :: tuple <を使い始めました。

template <typename> class object; 
template <typename... Rs> class object<std::tuple<Rs...> > { 
}; 

私はこれらのオブジェクトは、「パック」に散在タイプvoidを持つことができるように意図しています。私は Aです...私はおそらくそれらを移動/コピーし、周りにこれらのオブジェクトを渡したい

Void type in std::tupleを参照)は、すでに彼らのデータメンバのどれもこのタイプ のタプルを「インスタンス化」できないことを認識していませんこれらの型のタプル。実際、上記の空のオブジェクト定義を使用して問題を再現できます。

私はようなものを使用して、それを動作させることができます:可変引数再帰でfrequenly使用されている「グループ化」構造体の

template <typename... Rs> struct TGrp {}; 

template <typename> class object; 
template <typename... Rs> class object<TGrp<Rs...> > { 
}; 

これらのタイプ、およびそれらが使用/作成されることはありません飽きないことを意味しています。テンプレートargsをグループ化するだけです。

しかし、私は、「オブジェクト」の署名を「ユーザーが期待する」タイプ/名前で構成したいと思っています。自動ラムダ:

基本的に、私はstd::tupleは「グループ」に使用され、唯一の方法を見つけることができ周りにこれらのオブジェクトのいずれかを渡すのいずれかの可能性のある方法を実験しました。

誰も説明できます:

  1. "自動" ラムダのは、このために働くことができますなぜですか?

    遅延テンプレート控除についてdiff b/w "auto"と "decltype(auto)"のように?

  2. これらのオブジェクトの1つを受け入れるための関数パラメータを設計する方法。

- この風変わり上の任意の洞察力のためのあなたのすべてに感謝

例:

#include <tuple> 
#include <iostream> 

#define GRP std::tuple  // IF 'tuple' used: compile error where noted below 
//#define GRP TGrp   // if THIS is used: all works, and TGrp() is never constructed 


// Grouping mechanism 
template <typename... Ts> struct TGrp { 
    TGrp() { 
     std::cout << "Never printed message\n"; 
    } 
}; 


// MAIN OBJECT (empty for forum question) 
template <typename> class object; 
template <typename... Rs> class object<GRP<Rs...> > { 
}; 



// Regular function     (does NOT work) 
void takeobj(object<GRP<void> >& obj) { (void)obj; } 

// Lambda - taking anything...  (only thing I could make WORK) 
auto takeobj_lambda = [](auto obj) { (void)obj; }; 

// Template func - taking anything (does NOT work) 
template <typename T> void takeobj_templ_norm(T obj) { (void)obj; } 
template <typename T> void takeobj_templ_clref(const T& obj) { (void)obj; } 
template <typename T> void takeobj_templ_lref(T& obj) { (void)obj; } 
template <typename T> void takeobj_templ_rref(T&& obj) { (void)obj; } 


int main() 
{ 
    object<GRP<void> > oval; 

    //takeobj(oval);     // <-- causes compile error 

    takeobj_lambda(oval); // works 

    //takeobj_templ_norm(oval);  // <-- also error 
    //takeobj_templ_clref(oval);  // <-- also error 
    //takeobj_templ_lref(oval);  // <-- also error 
    //takeobj_templ_rref(oval);  // <-- also error 
    return 0; 
} 

編集

#include <tuple> 


// MAIN OBJECT (empty for forum question) 
template <typename> class object; 
template <typename... Rs> class object<std::tuple<Rs...> > { 
}; 

// Regular function     (does NOT work) 
void takeobj(object<std::tuple<void> >& obj) { (void)obj; } 

// Lambda - taking anything...  (only thing I could make WORK) 
auto takeobj_lambda = [](auto obj) { (void)obj; }; 


int main() 
{ 
    object<std::tuple<void> > oval; 

    //takeobj(oval);     // <-- causes compile error 
    takeobj_lambda(oval); // works 

    return 0; 
} 
+3

[簡単なコードを再現する](http://goo.gl/i1xlK6) –

+0

@ M.M私はここに新しく投稿しました。あなたはより良いサンプルを求めていたと思っていました...そのリンクをクリックしました。クールなインタラクティブなページ。そして、私が見ているのは短い例です。 – CrashNeb

+0

も:私はので、私は「より良い」クランのエラーメッセージを表示することができたM.Mからページを使用して、Visual Studioの2015を使用しています。 ;) はまだかかわらず、なぜラムダの(内部で生成された)クラステンプレートは、このテンプレートはできない「構築されたユーザーは、」管理するのですか? – CrashNeb

答えて

5

std::tuple<void>:ダウントリミング再生を追加します関連するですassobject<std::tuple<void>>であるため、引数に依存する検索が実行される非修飾呼び出しでは、std::tuple<void>がインスタンス化されて、インラインで定義された可能性のあるfriend関数を検索します。このインスタンス化によってエラーが発生します。呼び出される事は関数または関数テンプレートに名前を付けていない場合

引数依存ルックアップが行われていません。したがって、ラムダを使用して作品 - takeobj_lambdaオブジェクトです。

修飾された呼び出し(::takeobj(oval))またはかっこtakeobj(takeobj)(oval))のいずれかを使用すると、コードがコンパイルされます。どちらもADLを無効にします。

+0

ああ男は(それを考え出すを想像することはできません)...どうもありがとうございました!それはちょうど3週間前、私はこの答えに遭遇していたた[余分な括弧を行う...](http://stackoverflow.com/a/24116818/5844631)、それをブックマークして、それを暗記しようとしました。しかし、悲しいかな、私は "移動"していて、ADLが問題であったという結論を出さずに、未知の時間を費やしていたでしょう。 – CrashNeb

関連する問題