2009-06-07

ユーザー定義オペレーターの正しい使用方法

ユーザ定義リテラルまとめ - xyuyuxの日記

よくみたら、ちゃんと規格に明言してあったらしい。

A declaration whose declarator-id is a literal-operator-id shall be a declaration of a namespace-scope function or function template (it could be a friend function (11.4)), an explicit instantiation or specialization of a function template, or a using-declaration (7.3.3). A function declared with a literal-operator-id is a literal operator. A function template declared with a literal-operator-id is a literal operator template.

13.5.8, p2

よって、グローバル名前空間に定義されているリテラルオペレーターは規格に違反している。何らかの名前空間の中で定義しなければならない。

しかも、using directiveは使えず、using declarationを使わなければならない。

namespace foo 
{
int operator "" _bar( const char*, std::size_t ) ;
}

void f()
{
    using foo::operator "" _bar ;

    auto x = "hello,world!"_bar ;
}

using declarationしか使えないというのは、少々問題がある。例えば、あるライブラリが100個のリテラルオペレーターを提供している場合、一体ライブラリのユーザーはどうやって、それを使えばいいのか。合法的で、しかも間違いを起こさない簡単な方法は、プリプロセッサを使うというものしか思いつかない。

// UsingLiteralOperator.h

#define LIBRARY_USING_LITERAL_OPERATOR() \
using lib::operator "" _hoge ;\
using lib::operator "" _hage ;\
//以下98個の同様な宣言


// user.cpp

#include < UsingLiteralOperatorHelper.h >

void f()
{
// 使いたいスコープの中でこのマクロを使う
LIBRARY_USING_LITERAL_OPERATOR()

//あとはご自由に。

}

あるいは

// UsingLiteralOperator.h

using lib::operator "" _hoge ;
using lib::operator "" _hage ;
//以下98個の同様な宣言


// user.cpp

void f()
{
// 使いたいスコープの中で#includeする
#include < UsingLiteralOperator.h >

// あとはご自由に。
}

どっちにしろ、あまり使いたくない。それに、いまさら使用に当たってプリプロセッサが事実上必須な言語仕様というのは、どうなんだろう。

1 comment:

xyuyux said...

正しく使おうとしたら非常に使いにくいですね。

なにか良い解決策があれば良いのですが今のところ思いつかないので、
一つずつ使いたいものをusing-declarationで宣言してもらった方が、
いくらかましかなと思っています。