の実装を理解しようとしていますstd::is_class
。私はいくつかの可能な実装をコピーしてコンパイルし、それらがどのように機能するかを理解したいと思っています。これが完了すると、すべての計算がコンパイル中に行われることがわかります(振り返ってみると、もっと早く理解できたはずです)。そのため、gdbは正確に何が起こっているのかについてこれ以上詳細を教えてくれません。
私が理解するのに苦労している実装はこれです:
template<class T, T v>
struct integral_constant{
static constexpr T value = v;
typedef T value_type;
typedef integral_constant type;
constexpr operator value_type() const noexcept {
return value;
}
};
namespace detail {
template <class T> char test(int T::*); //this line
struct two{
char c[2];
};
template <class T> two test(...); //this line
}
//Not concerned about the is_union<T> implementation right now
template <class T>
struct is_class : std::integral_constant<bool, sizeof(detail::test<T>(0))==1
&& !std::is_union<T>::value> {};
コメントされた2行に問題があります。この最初の行:
template<class T> char test(int T::*);
どういうT::*
意味ですか?また、これは関数宣言ではありませんか?見た目は1つですが、関数本体を定義せずにコンパイルします。
私が理解したい2行目は次のとおりです。
template<class T> two test(...);
繰り返しますが、これは本体が定義されていない関数宣言ではありませんか?また、この文脈で省略記号はどういう意味ですか?関数の引数としての省略記号には、...
?の前に1つの定義済み引数が必要だと思いました。
このコードが何をしているのか理解したいと思います。標準ライブラリからすでに実装されている関数を使用できることはわかっていますが、それらがどのように機能するかを理解したいと思います。
参照:
あなたが見ているのは、「置換の失敗はエラーではない」の略である「SFINAE」と呼ばれるプログラミング技術です。基本的な考え方は次のとおりです。
namespace detail {
template <class T> char test(int T::*); //this line
struct two{
char c[2];
};
template <class T> two test(...); //this line
}
この名前空間は、に2つのオーバーロードを提供しますtest()
。どちらもテンプレートであり、コンパイル時に解決されます。最初のものはint T::*
引数としてを取ります。これはMember-Pointerと呼ばれ、intへのポインターですが、クラスTのメンバーであるintへのポインターです。これは、Tがクラスの場合、有効な式にすぎません。2つ目は、任意の数の引数を取ることです。これはどのような場合でも有効です。
それで、それはどのように使用されますか?
sizeof(detail::test<T>(0))==1
さて、関数a 0を渡します-これはポインター、特にメンバーポインターである可能性があります-これからどのオーバーロードを使用するかについての情報は得られません。したがって、Tがクラスの場合T::*
、...
ここではとオーバーロードの両方を使用できます。T::*
オーバーロードはここではより具体的なものであるため、使用されます。しかし、Tがクラスでない場合、次のようなものはT::*
あり得ず、オーバーロードの形式が正しくありません。しかし、テンプレートパラメータの置換中に発生した失敗です。また、「置換の失敗はエラーではない」ため、コンパイラはこの過負荷を黙って無視します。
その後がsizeof()
適用されます。戻り値の型が異なることに気づきましたか?したがってT
、コンパイラに応じて、適切なオーバーロード、したがって適切な戻り値の型を選択し、サイズがまたはのいずれsizeof(char)
かになりsizeof(char[2])
ます。
そして最後に、この関数のサイズのみを使用し、実際に呼び出すことはないため、実装は必要ありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加