ユーザ定義リテラルs
は、それらの異なる引数リストの上に、彼らはスコープの両方にある場合でも、seconds
とstring
間の「衝突」しません:
string operator "" s(const char* str, size_t len);
seconds operator "" s(unsigned long long sec);
互いに競合しない、まだ
using namespace std
で
void test1()
{
using namespace std;
auto str = "text"s;
auto sec = 1s;
}
は、両方のサフィックスがスコープ内にあり、かつ:
これは、このテストを実行することによって証明されます。
なぜinline namespace
が踊っていますか?
プログラマが望むように標準定義された名前を少ししか公開しないことを可能にすることが理論的根拠です。上のテストでは、stdライブラリ全体をtest
に "インポート"しました。少なくとも#includeされているものと同じくらいです。
test1()
namespace literals
はinline
ではありませんでした。ここで
は全体のstdをインポートせずに、リテラルを使用するには、より制限的な方法です:
void test2()
{
using namespace std::literals;
auto str = "text"s;
auto sec = 1s;
string str2; // error, string not declared.
}
これは、すべてのSTD-定義されたリテラルをもたらしますが、ではない(例えば)std::string
。
test2()
namespace string_literals
がinline
ではなく、namespace chrono_literals
がinline
ではない場合、機能しません。
あなたはまた、単に文字列リテラルを公開に選択し、することができないクロノリテラル:
void test3()
{
using namespace std::string_literals;
auto str = "text"s;
auto sec = 1s; // error
}
それともクロノリテラルではなく文字列リテラル:最後にそこ
void test4()
{
using namespace std::chrono_literals;
auto str = "text"s; // error
auto sec = 1s;
}
クロノの名前のすべてを公開する方法ですと chrono_literals:
void test5()
{
using namespace std::chrono;
auto str = "text"s; // error
auto sec = 1s;
}
test5()
は魔法のこのビットを必要とします。要するに
namespace chrono { // hoist the literals into namespace std::chrono
using namespace literals::chrono_literals;
}
、inline namespace
sが開発者にこれらのオプションのすべてが利用できるようにするツールです。
更新
OPは以下のいくつかの良いフォロー質問をします。このアップデートでは(うまくいけば)対応しています。
using namespace std
はいいですか?
によって異なります。 A using namespace
は、汎用目的のライブラリの一部であることを意図したヘッダーのグローバルスコープでは決して良い考えではありません。ユーザーのグローバル名前空間に多数の識別子を強制したくない。その名前空間はあなたのユーザーに属します。
グローバルスコープusing namespace
は、作成しているアプリケーションにのみヘッダーが存在し、そのヘッダーを含むすべてのもので使用可能なすべての識別子がある場合は、大文字でも構いません。しかし、あなたがグローバルスコープにダンプする識別子が多いほど、何かと衝突する可能性が高くなります。 using namespace std;
は識別子ののバンチを持ち込み、標準の新しいリリースごとにさらに多くをもたらします。だから私はusing namespace std;
あなた自身のアプリケーションのためにヘッダーのグローバルスコープでお勧めしません。
しかし、私はusing namespace std::literals
またはusing namespace std::chrono_literals
をヘッダー内のグローバルスコープで見ることができますが、アプリケーションヘッダーのみであり、ライブラリーヘッダーではありません。
私はusing
ディレクティブを関数スコープで使用したいのですが、識別子のインポートは関数のスコープに制限されています。このような制限で、競合が発生した場合は、修正する方がずっと簡単です。そして、最初は起こりにくいです。
std定義のリテラルは、となります。は、おそらく互いに矛盾しません(今日はありません)。しかし、あなたは
STD-定義されたリテラルは、ユーザー定義リテラルと決して競合がSTD-定義されたリテラルは_
で始めることは決してありませんしますので...わかりませんし、ユーザ定義リテラルは_
で開始するを持っています。
また、ライブラリ開発者にとっては、大きなライブラリの複数のインラインネームスペース内に競合するオーバーロードがないことが必要ですか?
これは本当に良い質問ですが、私は陪審員がまだこれに出ていないと考えています。しかし、ちょうどが意図的にに異なるインラインネームスペースのユーザー定義リテラルを持つライブラリを開発しています。
https://github.com/HowardHinnant/date
#include "date.h"
#include "julian.h"
#include <iostream>
int
main()
{
using namespace date::literals;
using namespace julian::literals;
auto ymd = 2017_y/jan/10;
auto jymd = julian::year_month_day{ymd};
std::cout << ymd << '\n';
std::cout << jymd << '\n';
}
上記のコードは、このエラーメッセージでコンパイルに失敗:
test.cpp:10:20: error: call to 'operator""_y' is ambiguous
auto ymd = 2017_y/jan/10;
^
../date/date.h:1637:1: note: candidate function
operator "" _y(unsigned long long y) NOEXCEPT
^
../date/julian.h:1344:1: note: candidate function
operator "" _y(unsigned long long y) NOEXCEPT
^
_y
リテラルがこのライブラリでyear
を作成するために使用されます。そしてこのライブラリには、グレゴリオ暦(date.h)とユリウス暦(julian.h)があります。これらのカレンダーのそれぞれはyear
クラス(date::year
とjulian::year
)です。グレゴリオ暦年はユリウス暦年と同じではないため、これらは異なる種類です。しかし、それらの名前をyear
とし、両方に_y
のリテラルを付けることは、まだ便利です。
Iは、次いで上記のコードからusing namespace julian::literals;
を削除する場合は、コンパイルし、出力:
2017-01-10
2016-12-28
2016年12月28日ジュリアンは2017年1月10日グレゴリオと同じ日であることを実証しています。そして、これはまた、同じ日が異なるカレンダーで異なる年を持つことができるグラフィックデモです。
私は矛盾する使用が問題になるかどうかは時間だけでわかります。これまでのところそれはなかった。しかし、グレゴリオ暦以外のカレンダーでこのライブラリを使用した人はあまりいません。
あなたの質問は、インラインネームスペース間のオーバーロードに関するものです。その時は大丈夫じゃない。 – Columbo
@Columbo確かに。また、 "インラインネームスペースは何ですか?"のためのdupではありません。なぜならその答えは* versioning * grmに関するものだからです。 – towi
Re: 'unsiged long long'、おそらくそれは' unsigned ... 'のタイプミスです。 – agc