3

ランダムな質問のようなもの...

私が探しているのは、キャスト元のクラス インスタンスの定義済み演算子を使用するキャスト操作を表現する方法であり、型に定義済みキャスト演算子がない場合はコンパイル時エラーを生成します。たとえば、私が探しているのは次のようなものです。

template< typename RESULT_TYPE, typename INPUT_TYPE >
RESULT_TYPE operator_cast( const INPUT_TYPE& tValue )
{
    return tValue.operator RESULT_TYPE();
}

// Should work...
CString sString;
LPCTSTR pcszString = operator_cast< LPCTSTR >( sString );

// Should fail...
int iValue = 42;
DWORD dwValue = operator_cast< DWORD >( iValue );

興味深い補足: 上記のコードは VS2005 C++ コンパイラをクラッシュさせ、VS2008 C++ コンパイラでは正しくコンパイルされません。これは、コンパイラのバグであると推測していますが、うまくいけばアイデアを示しています。

この効果を達成する方法を知っている人はいますか?

編集:これを使用する理由を説明するためのより多くの理論的根拠。型をカプセル化または抽象化することになっているラッパー クラスがあり、それをカプセル化された型にキャストしているとします。static_cast<> を使用することもできますが、失敗させたい場合に機能する可能性があります (つまり、コンパイラーは、要求した型に変換できる演算子を選択します。その演算子が存在しないために失敗したい場合)。

確かに、これはまれなケースですが、カプセル化された関数でコンパイラに実行してもらいたいことを正確に表現できないのは面倒です...したがって、ここで質問します。

4

4 に答える 4

3

投稿したコードはCameau コンパイラで動作します(これは通常、有効な C++ であることを示しています)。

ご存じのように、有効なキャストはユーザー定義のキャストを 1 つしか含まないため、キャスト テンプレートで新しい型を定義し、キャストが利用できないことを静的にアサートすることで、別のユーザー定義のキャストを追加することを考えていました。結果の型への新しい型 ( boost is_convertibleを使用)。ただし、これはキャスト演算子とキャスト コンストラクター (1 つの引数を持つ ctor) を区別せず、追加のキャストを実行できます (例: void*to bool)。キャスト演算子とキャストコンストラクターを区別することが正しいことかどうかはわかりませんが、それが質問の内容です。

これについて数日熟考した後、キャストオペレーターのアドレスを簡単に取得できます。これは、メンバー構文への C++ の毛むくじゃらのポインターのため、言うよりも実行するのが少し簡単です (正しく理解するのに予想以上に時間がかかりました)。これがVS2008で機能するかどうかはわかりません。Cameauでのみ確認しました。

template< typename Res, typename T>
Res operator_cast( const T& t )
{
    typedef Res (T::*cast_op_t)() const;
    cast_op_t cast_op = &T::operator Res;
    return (t.*cast_op)();
}

編集: VS2005 と VS2008 でテストする機会がありました。私の調査結果は、元のポスターとは異なります。

  • VS2008 では、元のバージョンは正常に動作しているようです (私の場合も同様です)。
  • VS2005 では、元のバージョンは組み込み型からキャストする場合 (int から int へのキャストなど) にのみコンパイラをクラッシュさせます。
于 2008-10-21T21:17:15.373 に答える
1

明示的にマークされた変換コンストラクターを使用することは、コンパイラーが暗黙的に変換された型がラッパー クラスを初期化することを許可しないようにする方法です。

于 2008-10-16T19:19:27.610 に答える
1

テンプレート関連のコンパイラ エラー メッセージは、通常、解明するのが完全な苦痛であるため、各変換を指定することを気にしない場合は、デフォルトのテンプレート定義も提供することで、失敗した場合にコンパイラがより有益なメッセージを出力するようにすることができます。これは、コンパイラが実際に呼び出されたテンプレート内のコードのみをコンパイルしようとするという事実を利用しています。

#include <string>

// Class to trigger compiler warning   
class NO_OPERATOR_CONVERSION_AVAILABLE
{
private:
   NO_OPERATOR_CONVERSION_AVAILABLE(){};
};

// Default template definition to cause compiler error
template<typename T1, typename T2> T1 operator_cast(const T2&)
{
   NO_OPERATOR_CONVERSION_AVAILABLE a;
   return T1();
}

// Template specialisation
template<> std::string operator_cast(const std::string &x)
{
   return x;
}
于 2008-10-16T21:12:09.957 に答える
0

テンプレートの特殊化が必要なように聞こえますが、次のようになります。

/* general template */
template<typename T1, typename T2> T1 operator_cast(const T2 &x);

/* do this for each valid cast */
template<> LPCTSTR operator_cast(const CString &x) { return (LPCTSTR)x; }

編集: 別の投稿で述べたように、サポートされていないキャストが実行された場合に、より有用なエラー メッセージを表示するために、一般的なバージョンに何かを追加できます。

于 2008-10-16T20:51:04.663 に答える