名前空間内で定義された user-defined literals を使う

今まで user-defined literals では名前空間を使えないと思い込んでいましたが,
規格を読むと,名前検索は普通の関数と同様に行われるようなので,普通に
名前空間内で定義し,その名前空間内で特に何も考えずに使用することも可能だし,
違う名前空間であっても, using 宣言を使うことで普通に呼び出せるようです.


具体例を挙げると,

#include <complex>
#include <type_traits>

#define STATIC_ASSERT(...) static_assert( __VA_ARGS__, #__VA_ARGS__ )

// 虚数単位は j 
inline constexpr std::complex<double> operator "" _j( long double imag ) {
  return std::complex<double>( 0, static_cast<double>(imag) );
}

namespace ns
{
  // 名前空間内で定義された 別の _j (区別のため float を使う)
  inline constexpr std::complex<float> operator "" _j( long double imag ) {
    return std::complex<float>( 0, static_cast<float>(imag) );
  }
  
  void f() {
    constexpr auto z = 1_j;
    // グローバルに operator "" _j はあるが, ns::operator "" _j が呼ばれる
    STATIC_ASSERT( std::is_same< decltype(z), std::complex<float> const >::value );
  }
}

namespace ns2
{
  void g() {
    // using 宣言で使う user-defined literals を指定
    using ns::operator "" _j;
    // グローバルの operator "" ではなく ns::operator "" _j が呼ばれる
    constexpr auto z = 1_j;
    // …筈なのだが上手くいかない. gcc のバグ?
    // STATIC_ASSERT( std::is_same< decltype(z), std::complex<float> const >::value );
  }
}

int main()
{
  ns::f(); ns2::g();
  
  constexpr auto z = 1_j;
  // グローバルの operator "" _j が呼ばれる
  STATIC_ASSERT( std::is_same< decltype(z), std::complex<double> const >::value );
}

上記のコードを最新の GCC4.7 (gcc-4.7-20111029)でコンパイルさせると,問題なくコンパイル通ります.


なので,やっぱ user-defined literals さんは滅びなくて正解だった…のかなぁ? うーん.