2016-11-14 33 views
1

したがって、関数としてパラメータを取る2つの汎用クラスがあります。 1つは関数ポインタをとり、もう1つはstd ::関数をとります。どちらもテンプレートパラメータを持っています。関数のポインタとstd :: functionを引数としてテンプレート化されたパラメータを持つ関数を渡す

#include <functional> 
#include <memory> 

namespace { 
    void example(const std::shared_ptr<const int>&) {} 
} 

class Generic { 
public: 
    Generic() {} 
    virtual ~Generic() {} 
    template <typename Targ> 
    void doWork(std::function<void(const std::shared_ptr<const Targ>&)> arg) {} 

    template <typename Targ> 
    void doWork2(void(*function)(const std::shared_ptr<const Targ>&)) {} 
}; 

class Special : public Generic { 
public: 
    Special() { 
     //doWork(&example); // Fail! 
     doWork<int>(&example); // OK! 
     std::function<void(const std::shared_ptr<const int>&)> func = &example; 
     doWork(func); // OK! 
     doWork2(&example); // OK! 
    } 
}; 

int main(int argc, char** argv) { 
    Special special; 
    return 0; 
} 

関数ポインタでは、関数はコンパイルされますが、std ::は機能しません。ここでテンプレート控除が失敗するのはなぜですか?

クランレポート:

example.cpp:27:9: error: no matching member function for call to 'doWork' 
     doWork(&example); 
     ^~~~~~ 
example.cpp:14:10: note: candidate template ignored: could not match 'function<void (const shared_ptr<const type-parameter-0-0> &)>' against 'void (*)(const std::shared_ptr<const int> &)' 
    void doWork(std::function<void(const std::shared_ptr<const Targ>&)> arg) { 
     ^
1 error generated. 
+0

'example'は' std :: function'ではなく、潜在的にこの関数からいくつかの 'std :: function'を構築することができます。 – Jarod42

+0

@ Jarod42しかし、 '&example'は関数ポインタです。関数ポインタを' std :: function'として渡すことはできますか? – Chris

答えて

2

テンプレート引数の減算は、そのようには機能しません。

テンプレート引数の減算は、パターンマッチです。 exampleは一部のタイプのstd::function<void(const std::shared_ptr<const Targ>&)>タイプのオブジェクトですTarg

変換可能ではありませんが、実際にそのタイプのオブジェクトは既にありますか?

いいえ、そうではありません。

しかし、すでに暗黙の減衰ルールを使用している関数ポインタです。

コンストラクタタイプのテンプレート引数を推定するC++ 17の機能があります。 std::functionは、この状況でC++ 17またはC++ 20が出てきたときに、関数ポインタから独自の型を学習するためにインストルメントされていても、いなくてもよい。私はC++の専門知識が不足していると確信しています。

+2

_私はC++の専門知識が不足していると確信しています。私はあなたのように専門知識が不足しています。 :-) – skypjack

1

コンストラクタはそれのクラスの種類を推測することはできませんので、これが起こります。私の文言は奇妙に聞こえる場合は、おそらくこの例は、役立ちます:

template <class T> 
class Example { 
    Example(const T&) { /*...*/ } 
}; 

私は、このようなtemplate <class T> void f(const Example<T>&)としての機能のテンプレートを、持っている場合、私はちょうどf(10)を行うことはできません。これがあなたのコードの趣旨です。 std::functionは、(非明示的な)コンストラクタに渡したものに基づいてテンプレートパラメータを知ることができません。

注:これは、ちなみに、C++の作品17です。

関連する問題