VS7.1 で記述されたコードを見つけたので、MacOSX で動作させようとしています。以下のコード スニペットは、 SFINAEの原則に関するものだと理解しています。私が理解していることから、コードは、コンパイル時にテンプレートのインスタンス化マジックに依存することで、何かの型を知るために使用されます。つまり、適切なオーバーロードは、テンプレート引数を確認することで選択されます。
これが私が持っているコードです。問題のみを表示するためにやや単純化されています。
template <typename T>
struct SomeClass
{
};
template <>
struct SomeClass<char>
{
typedef char Type;
};
template <typename T>
struct IsChar
{
typedef char Yes;
typedef int No;
template <typename U>
static Yes Select(U*, typename SomeClass<U>::Type* p = 0);
template <typename U>
static No Select(U*, ...);
static T* MakeT();
const static bool Value = sizeof(Select(MakeT())) == sizeof(Yes);
};
私は単にこれを次のように使用しています:
if (IsChar<int>::Value)
{
...
上記のコードをコンパイルすると、int を使用するときに Type の typedef が欠落しているため、適切に動作し、最上位のクラスが選択されます。
代わりに char を使用すると...
if (IsChar<char>::Value)
{
...
...コンパイラは、どちらを使用するかわからないため、あいまいな Select 関数について文句を言います。私が読んだことから、オーバーロードの解決では、省略記号パラメーターが優先されません (...)。したがって、最初のものを選択することを知っている必要があります。
コードは少なくとも VS7.1 では正常に動作していましたが、MacOSX の gcc や Linux の gcc4.4 では動作しませんでした。
これを修正する方法はありますか?多分それは通常別の方法で行われますか?
ありがとう!
更新: 私が提供したサンプル コードが少し単純化しすぎていることに気付きました。誤ってそのように見せたとしても、ここで型をチェックしているとは思えないからです。ここにコードがないので、今夜はもう少し情報を集める必要があります。そのために残念。
UPDATE2: 元のコードに慣れていないか、このようにテンプレートを使用していることが原因で、私のプレゼンテーションが悪い場合でも。その間、もう少し情報を掘り下げます。これらの構造が何らかの理由で X にあり、私が指定した名前がすべて間違っていると仮定しましょう。コンパイラの問題はどうですか? ここで適切なオーバーロードされた関数を選択できないのはなぜですか? これは私も興味深いです。私が言ったように、私は全体的な目的が何であるかをよりよく説明して戻ってきます.
編集
元のコードを詳しく見てみると、ここで提案されているように、boost::integral_constant と boost::enable_if を使用しています。問題は、テンプレートの引数がどのように推定されるかに特有のものであり、セットアップされた方法では機能しませんでした。ただし、ゲオルクが回答の最後に提案したことに従って、物事を修正して受け入れることができました。私は今、次のものを持っています:
typedef char Yes;
typedef int No;
template <typename U> static Yes Select(typename SomeClass<U>::Type* p);
template <typename U> static No Select(...);
static const bool Value = sizeof(Select<T>(0)) == sizeof(Yes);
これはうまくいきます。少し実験していると、Select 関数に 2 つの関数パラメーターがあると問題が発生することがわかりました。理由はわかりません。物事をよりよく理解したら、これに戻ります。
ご助力いただきありがとうございます。少なくとも、ここでの原則と、物事がどのように機能するかを理解しています。まだ不明な詳細のみ。