2012-02-16

ユーザー定義リテラル補足

前回、ユーザー定義リテラルのすべてを説明したつもりであったが、いくつか細かい漏れがあった。

まず、ユーザー定義リテラルの宣言であるが、実は文法上、空白文字が必要な箇所がある。""と識別子の間だ

int operator "" /*ここに少なくともひとつの空白文字が必要*/ _identifier( unsigned long long int ) ;

空白文字を入れないと、""_identiferがひとつのトークンだとみなされてしまう。

もちろん、この宣言を参照する際にも、空白文字が必要である。

operator "" /*空白文字が必要*/ _identifer( 123ULL ) ;

また、ユーザー定義リテラルのオーバーロードは、あらかじめ定められた仮引数リストやテンプレートしか使えないが、その他は、普通の関数と変わりないということである。もちろん、inlineやconstexprで宣言することもできる。当然、内部リンケージを持つ可能性もある。

inilne unsigned long long int operator "" _inline_udl( unsigned long long int value ) { return value ; }
constexpr unsigned long long int operator "" _constexpr_udl( unsigned long long int value ) { return value ; }

もちろん、アドレスだって取得できる。

unsigned long long int operator "" _udl( unsigned long long int value ) { return value ; }

int main()
{
    using udl_pointer_type = unsigned long long int (*)( unsigned long long int ) ;
    // アドレスの取得
    udl_pointer_type p = &operator "" _udl ;
}

また、当然ながら、名前空間スコープ内に宣言される。名前解決も通常通りである。

namespace foo
{
unsigned long long int operator "" _udl( unsigned long long int value ) { return value ; }
}


int main()
{
    123_udl ; // エラー
    {
        using namespace foo ;
        123_udl ; // OK
    }

    {
        using foo::operator "" _udl ;
        123_udl ; // OK
    }
}

もちろん、オーバーロード解決も通常通りである。

void operator "" _udl( unsigned long long int value ) {  } // #1
void operator "" _udl( long double value ) { } // #2

int main()
{
    operator "" _udl( 123ULL ) ; // #1
    operator "" _udl( 1.23L ) ; // #2
}

また、文字列やテンプレート実引数で受け取る場合のオーバーロードの優先順位は、

  1. 整数リテラルの場合、仮引数unsigned long long int、浮動小数点数リテラルの場合、long double
  2. それが見つからない場合、char const *
  3. それが見つからない場合、テンプレート実引数

となっている。したがって、

void operator "" _u1( unsigned long long int value ) {  } // #1
void operator "" _u1( char const * ) { } // #2

void operator "" _u2( char const * ) {  } // #3
template < char ... Types >
void operator "" _u2( ) { } // #4

int main()
{
    123_u1 ; // #1
    123_u2 ; // #3
}

このようにオーバーロード解決される。

つまり、いくつかの制限と例外的なルールを除けば、およそ関数に適用されるルールは、ユーザー定義リテラルのオーバーロードにも適用される。

No comments: