2016-04-12 2 views
15

C++(GCC 4.8.3)を使用して、私はtypeid(T1).name()typeid(T2).name()が同じであるが、 std::is_same<T1, T2>::valuefalseあるという奇妙な性質を持っている2種類(T1T2)を持っています。同じタイプID名ではなく、はstd :: is_same

どのようにすることができますか?どのような理由があるのか​​をさらに調べるにはどうすればよいでしょうか?

+6

'トップレベルの修飾子を無視しtypeid'。 –

+1

^^これはconstと& –

+0

@SergeyAのようなものなので、typeidには実質的に使用されていないか、何か不足していますか? – user463035818

答えて

5

typeidすべてCV-修飾子を無視する:すべての場合において

、CV-修飾子はタイプIDによって無視される(すなわち、型ID(T)==型ID(CONST T)である)

(ref)

これはtypeidは(少数を示すために)すべての参照&constを無視することを意味します。

int i = 0; 
const int&& j = 1; 

if (typeid(i).hash_code() == typeid(j).hash_code()) //returns true 
    std::cout << "typeid(int) == typeid(const int&&)"; 

のみ2つの機能のために、それは2と同じtypeid sが同じであることが保証されているため、2 typeid Sを比較するための注意、あなたは、typeid(T).hash_code()またはstd::type_index(typeid(T))のいずれかを使用する必要があります。参考文献を比較してもその保証はありません。

オブジェクトTYPE_INFOこれらのSTD :: TYPE_INFO :: hash_codeは同一であるが、同じのstd ::インスタンスTYPE_INFOは、同じ型の型IDの表現のすべての評価によって参照されるという保証はありませんが、それらのstd :: type_indexと同じです。

(ref)


@Yakkが述べた、として、あなたはあなたが望んでいた動作を取得するために std::remove_referencestd::remove_cvを使用することができます。

std::remove_referenceは、Tのすべての参照を削除し、constvolatileの修飾子をすべて削除します。 std::is_sameに渡す前にTにこれらの関数を渡す必要があります。std::is_sameは、基底型(存在する場合)(とT2)のみを比較します。

+3

'演算子=='は、同じ型の記述子についても 'true'を評価することが保証されています。したがって、 '&typeid(T)==&typeid(T)'を確実に比較することはできませんが、 'typeid(T)== typeid(T)'を比較して 'true 'を確実に得ることができます。 – Angew

+1

'remove_reference'と' remove_cv'を挙げると、OPが根本的な問題(ヘッドラインの問題だけでなく)を解決するのに役立つかもしれません。 – Yakk

12

多型を無視すると、typeid()は、式の静的型を表すオブジェクトを提供します。しかし、式の型に関しては無視される要素があります。 [式]から:式は、最初のタイプ「Tへの参照」(8.3.2、8.5.3)を有する

場合、タイプはT前さらなる分析 に調整します。 [...] prvalueは最初Tが -unqualified非クラスは、非アレイタイプ、 のタイプは発現がT前に任意に調整するCVあるタイプ「CVT」を有する場合さらなる分析。

結果、トップレベルCV -qualificationまたは参照のみが異なる任意のタイプが同じタイプIDが得られます。たとえば、int,const int,int&volatile const int&&などはすべて同じtypeid()となります。

基本的には、あなたの最初の思考プロセスだった:

typeid(T) == typeid(U) <==> std::is_same<T, U> 

しかし、正しい同値である:

typeid(T) == typeid(U) <==> std::is_same<expr_type<T>, expr_type<U>> 

template <class T> 
using expr_type = std::remove_cv_t<std::remove_reference_t<T>>; 
関連する問題