次のセーフ bool イディオムからの抜粋を考えてみましょう。
typedef void (Testable::*bool_type)() const;
operator bool_type() const;
typedefなしで変換関数を宣言することは可能ですか? 以下はコンパイルされません。
operator (void (Testable::*)() const)() const;
次のセーフ bool イディオムからの抜粋を考えてみましょう。
typedef void (Testable::*bool_type)() const;
operator bool_type() const;
typedefなしで変換関数を宣言することは可能ですか? 以下はコンパイルされません。
operator (void (Testable::*)() const)() const;
identity
ああ、メタ関数を思い出した。書くことが可能です
operator typename identity<void (Testable::*)() const>::type() const;
を次のように定義しますidentity
。
template <typename T>
struct identity
{
typedef T type;
};
identity
まだ a を使用していると主張することもできますがtypedef
、この解決策は私にとって十分に「良い」ものです。
typedef
が必要な1つのケース(あなたの質問とは無関係)は、
va_arg()
大きい。C99標準(7.15.1.1)の引用:
type * va_arg(va_list ap、type);
..。
パラメータタイプは、指定されたタイプを持つオブジェクトへのポインタのタイプが、タイプに*を後置するだけで取得できるように指定されたタイプ名でなければなりません 。
「typedef が絶対に必要な場合はありますか?」という質問への回答 質問のタイトルから、typedef が必要な場所の一例を次に示します。
f(unsigned char()); // compiler error!
typedef unsigned char Byte;
f(Byte()); // fine!
ここで結果を参照してください: http://ideone.com/JPUra
私の分析によると、 を使用しないと不可能typedef
です。コンパイラはを最初のトークンとして認識し、引数を持たない を(
オーバーロードしていると想定します(引数は次の括弧のセットに入ります)。() operator
余分な括弧のセットを入れても役に立ちませんが、実際にはコンパイラを混乱させるため、より多くのエラーが発生します。
ほとんどの STL コードはtypedef
initions の上にあり、それらを使用する必要があります。
あなたの場合、文法では typedef を使用する必要があるようです。conversion-function-idは、 operator conversion-type-idの形式でなければなりません。conversion-type-idに括弧を含めることはできません。したがって、関数へのポインター型またはメンバー関数へのポインター型に変換する場合は、typedef を使用する必要があります。
C++11 では、次のようにできます (gcc 4.5.2):
operator decltype((void (Testable::*)() const)(0))() const ;
綺麗とは言ってない…
私はclang ++でこの問題に出くわしました:
foo.cpp:17:8: error: must use a typedef to declare a conversion to 'void (*(int))()'
また、identity<T> 機能をカバーする C++11 STL テンプレートがあります。
#include <type_traits>
…
struct foo {
void bar( ) const { }
operator std::common_type<void(foo::*)( )const>::type( ) { return &foo::bar; }
};
Atypedef
はマクロではありません。2 番目の例は最初の例と同等ではありません。最初のケースでtypedef
は、ファンクターを定義してから、ファンクター型のキャスト演算子でその型を使用しています。2 番目の例では、型がないために演算子が指定されていないため、演算子は不適切な構文を使用しています。どのように書くかはわかりませんが、通常は方法があります。
Typedef は、TMP で人間が読めるコードを作成する場合を除いて、実際には必要ありません。
別の構文が思いつかないので、場合によっては typedef が必要になるかもしれません。私はちょうど別のものを考えました。以下のような戻り値の型を持つ静的メソッドを含む、特殊化されたテンプレートがあるとします。
template <typename T>
struct WhateverHandler
{
typedef T rType;
static rType Whatever() { return rType(); }
};
template <>
struct WhateverHandler<std::string>
{
typedef std::string rType;
static rType Whatever() { return rType(); }
};
この場合、特殊化に関係なく静的メソッドを呼び出すために typedef が必要になると思います。そうしないと、戻り値の型が異なるため、メソッドがコンパイラを混乱させる可能性がありますが、適切なオーバーロードにはなりません。
template <typename T>
struct WhateverUser
{
typename WhateverHandler<T>::rType DoWhatever()
{
return WhateverHandler<T>::template Whatever();
}
};