2016-12-10 6 views
3

これはC++でのテンプレート問題の一般的なスケルトンバージョンです。私は、fooから呼び出されたときにbarファンクションテンプレートをもっともらしい候補として認識させる方法を考え出すことはできません。C++候補テンプレートstd :: functionの引数としてラムダを渡すときに無視されるエラー

#include <iostream> 
#include <cstdlib> 
#include <unordered_map> 

template<class T> 
std::unordered_map<std::string, T> getStr2TMap() { 
    return {}; // suppose logic here is a bit more involved 
} 

template<class T> 
std::unordered_map<int, T> getInt2TMap() { 
    return {}; // suppose logic here is a bit more involved 
} 

template<class U, class T> 
void bar(
    const std::function<void (std::unordered_map<U, T>&&)>& baz 
) { 
    if (rand() % 2 > 0) { 
    baz(getInt2TMap<T>()); 
    } else { 
    baz(getStr2TMap<T>()); 
    } 
} 

template<class T> 
void foo(
    const std::unordered_map<std::string, T>& map1 
) { 
    bar([&map1](auto&& map2) { 
    // do some things with map1 and map2 
    }); 
} 

int main() { 
    std::unordered_map<std::string, int> myMap; 
    foo<int>(myMap); 
} 

EDIT

コードの多くは単純化されたバージョン、同じエラー。私はこのバージョンではなく、上記のバージョンのソリューションを探しています。

#include <iostream> 
#include <functional> 
#include <unordered_map> 

template<class T> 
void foo(
    const std::function<void (std::unordered_map<int, T>&&)>& bar 
) { 
    std::unordered_map<int, T> myMap; 
    bar(myMap); 
} 

int main() { 
    foo([](auto&& m) { 
    }); 
} 
+0

ここでの問題の一部は、私は私が 'foo'呼び出すときに明示的に型引数を渡す必要があるということであるように見えますか?それを推論する方法はありますか? – Kvass

答えて

3

示すコードが控除試行がテンプレート関数に渡されるラムダパラメータのためのものである以下のタイプ

std::function<void (std::unordered_map<U, T>&&)> 

ためTUを推定しようとする:

[&map1](auto&& map2) {} 

問題ラムダは何らかの種類のstd::functionではないということです。 ...

"閉鎖" タイプとして知られているユニークな無名の非組合非集約クラス タイプの一時オブジェクト、...

Cite

:それはあります

別の言い方をすれば、ラムダオブジェクトはラムダコードを実行するoperator()のクラスのインスタンスです(キャプチャされたオブジェクトは名前のないクラスのメンバーに変換されます)。したがって、それはstd::functionではないので、std::functionのタイプを推測することはできません。それは呼び出し可能なタイプがあるので

、しかし、std::functionに変換することができます。

bar(static_cast<std::function<void(std::unordered_map<std::string, T> &&)>> 
     ([&map1](auto&& map2) { 
      // do some things with map1 and map2 
     })); 
} 

は、それが認識bar()テンプレート関数を取得します。

は、しかし、まだ示されているコードの第2の問題があります:

if (rand() % 2 > 0) { 
    baz(getInt2TMap<T>()); 
    } else { 
    baz(getStr2TMap<T>()); 
    } 

サイコロのロールに応じて、コードは、文字列の順序なしマップ、またはint型の順不同のマップのいずれかを渡ししようとしますbaz()

これは...動作しません。ゲームのこの段階では、bazは何らかの種類のstd::functionです。それはテンプレートではありません。したがって、1つのタイプのパラメータしか取ることができません。あなたはstatic_castことを追加し、bar()作る場合

baz(getStr2TMap<T>()); 

は、呼び出し元が文字列の順序なしマップを渡しているという事実と一致するように、結果のコードをコンパイルする必要があります。

bar()内で何が起こっているのかは別の問題です。static_castを使用すると、候補テンプレートを取得する方法の質問に答えますbarが認識されます。

+0

'rand()'のことは、実際にキーの種類がわからないところで、もっと複雑なロジックに近づける試みでした。実際には、2つの異なるキータイプ、1つの未知のキータイプを処理する必要はありません。私はここでそれを単純化することに失敗したと思う。 – Kvass

1

サムは、barUがどのように矛盾しているかをよく観察します。しかし、あなたの簡単な例では、なぜあなたが書くことができるconst std::function<void (std::unordered_map<int, T>&&)>&のすべての問題を経る:

#include <iostream> 
#include <functional> 
#include <unordered_map> 

template<class T, class Func> 
void foo(
    Func bar 
) { 
    std::unordered_map<int, T> myMap; 
    bar(myMap); 
} 

int main() { 
    // needs the hint for T, since it isn't used anywhere 
    foo<int>([](auto&& m) { 
    }); 
} 
関連する問題