私はそのような関数定義を持っています
template <typename T>
auto print(T t) -> decltype(t.print()) {
return t.print();
}
アイデアは、引数が型T
でなければならず、print
関数を持たなければならないということです。このprint
関数は何でも返すことができ、 の必要性を説明していますdecltype
。たとえば、次のことができます。
struct Foo
{
int print()
{
return 42;
}
};
struct Bar
{
std::string print()
{
return "The answer...";
}
};
...
std::cout << print(Foo()) << std::endl;
std::cout << print(Bar()) << std::endl;
/* outputs:
42
The answer...
*/
テンプレートはランタイムのインスタンス化を行うことができず、クラスを基本クラスから派生させ、その型を決定して使用するテンプレート引数を確認できることを読みました。ただし、non-class
タイプに対してこれを行うにはどうすればよいですか? アイデアは、次のものを持つことができることです:
template <typename T>
T print(T t) {
return t;
}
同様に、しかしこれは私にあいまいな過負荷エラーを与えます。予選は機能しませんprint<Foo>
。もう 1 つの問題は、次のようなファンクタがある場合はどうなるかということです。
struct Foo
{
virtual int print();
operator int() const
{
return 42;
}
};
それは今どのように決定されますか?
私の質問は、これらすべてのあいまいさをテンプレートで解決することは可能ですか、それとも冗長なコードをたくさん書く必要があるのでしょうか?
テスト
テストを段階的に追加し、編集した各ソリューションを下からコピー/貼り付けました。結果は次のとおりです。
次のクラスを使用します。
struct Foo
{
int print()
{
return 42;
}
operator int() const
{
return 32;
}
};
struct Bar
{
std::string print()
{
return "The answer...";
}
operator int() const
{
return (int)Foo();
}
};
struct Baz
{
operator std::string() const
{
return std::string("The answer...");
}
};
そして、次のテスト出力:
std::cout << print(Foo()) << std::endl;
std::cout << print(Bar()) << std::endl;
std::cout << print(42) << std::endl;
std::cout << print((int)Foo()) << std::endl;
std::cout << print("The answer...") << std::endl;
std::cout << print(std::string("The answer...")) << std::endl;
std::cout << print((int)Bar()) << std::endl;
std::cout << print((std::string)Baz()) << std::endl;
どちらも正しく出力されます:
42
The answer...
42
32
The answer...
The answer...
32
The answer...