この例を考えてみましょう。
#include <memory>
template<typename T>
class A {};
template<typename T1, typename T2>
class B: public A<T1> {};
template<typename T = int>
void foo(std::shared_ptr< A<T> > test)
{
}
int main()
{
auto p = std::make_shared<B<int, int>>();
foo<int>(p); // Works
foo<>(p); // Does not work
foo(p); // Does not work
}
fooのタイプTを明示的に指定せずにこれをコンパイルしようとしていますが、機能しません。明示的にT型を指定した場合、問題なく動作する理由はわかりませんが、T型を指定しない場合は、コンパイラにT型を指定したとしても、コンパイルされません。明示的に指定してください。
コンパイラが型Tを推測できない理由はわかりますが、指定しないとデフォルトの型Tを使用できないのはなぜですか?これを回避するにはどうすればよいですか。また、これを行う「適切な」方法は何ですか。
この問題は、デフォルトのテンプレートパラメータとは関係ありません。代わりに、p
(std::shared_ptr<B<int, int>>
)のタイプをstd::shared_ptr<T>
テンプレートの引数と照合することはできませんfoo
。テンプレートの引数の推定中、変換は考慮されず、派生クラスインスタンスへの参照を基本クラス参照として渡すことは実際に変換です。
std::shared_ptr
管理するポインタを明示的にアップキャストすることで、問題を修正できます。
std::shared_ptr<A<int>> p = std::make_shared<B<int, int>>();
これで、これらの呼び出しは期待どおりに機能します。
foo<>(p); // Ok, argument matches the signature
foo(p); // Same...
テンプレートの引数の型が関数テンプレートのパラメータリストに表示されるかどうか(推論が可能になるかどうか)に大きな違いがあることに注意してください。これらの2つのテンプレートを検討してください。
template <class T = int> void foo(T&&)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
template <class T = int> void bar(double)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
どちらもデフォルトのタイプですが、int
このようにインスタンス化されると
foo<>(0.0); // outputs: void foo(T&&) [with T = double]
bar<>(0.0); // outputs: void bar(double) [with T = int]
最初のインスタンス化は関数の引数を使用してテンプレートパラメーターを推定します(結果はdouble
)。2番目のインスタンス化は何も推定せず、デフォルトでint
。になります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加