名前空間
変種
操作

翻訳単位ローカルエンティティ (C++20以降)

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

翻訳単位ローカル (TU-local) エンティティは、ローカルであるべきエンティティ (他の翻訳単位では使用されないもの) が、他の翻訳単位で公開され、使用されることを防ぐために導入されます。

Understanding C++ Modules: Part 2からの例は、公開を制約しない問題を示しています。

// Module unit without TU-local constraints
export module Foo;
 
import <iostream>;
 
namespace
{
   class LolWatchThis {        // internal linkage, cannot be exported
       static void say_hello()
       {
           std::cout << "Hello, everyone!\n";
       }
   };
}
 
export LolWatchThis lolwut() { // LolWatchThis is exposed as return type
    return LolWatchThis();
}
// main.cpp
import Foo;
 
int main()
{
    auto evil = lolwut();        // 'evil' has type of 'LolWatchThis'
    decltype(evil)::say_hello(); // definition of 'LolWatchThis' is not internal anymore
}

目次

[編集] TU-local エンティティ

エンティティがTU-localであるのは、以下のいずれかの場合です。

  1. 以下のいずれかの型、関数、変数、またはテンプレートである場合。
    1. 内部リンケージを持つ名前がある、または
    2. リンケージを持つ名前がなく、TU-local エンティティの定義内で宣言されている、またはラムダ式によって導入されている場合。
  2. クラス指定子、関数本体、または初期化子の外で定義されている名前のない型、またはTU-local エンティティのみを宣言するために使用される定義型指定子 (型指定子、クラス指定子、または列挙指定子) によって導入された型である場合。
  3. TU-local テンプレートの特殊化である場合。
  4. いずれかの TU-local テンプレート引数を持つテンプレートの特殊化である場合、または
  5. その (おそらくインスタンス化された) 宣言が露出 (後述) であるテンプレートの特殊化である場合。
// TU-local entities with internal linkage
namespace { // all names declared in unnamed namespace have internal linkage
    int tul_var = 1;                          // TU-local variable
    int tul_func() { return 1; }              // TU-local function
    struct tul_type { int mem; };             // TU-local (class) type
}
template<typename T>
static int tul_func_temp() { return 1; }      // TU-local template
 
// TU-local template specialization
template<>
static int tul_func_temp<int>() { return 3; } // TU-local specialization
 
// template specialization with TU-local template argument
template <> struct std::hash<tul_type> {      // TU-local specialization
    std::size_t operator()(const tul_type& t) const { return 4u; }
};

値またはオブジェクトがTU-localであるのは、以下のいずれかの場合です。

  1. それが TU-local 関数であるか、TU-local 関数へのポインタであるか、または TU-local 変数に関連付けられたオブジェクトである場合、または
  2. それがクラスまたは配列型のオブジェクトであり、そのサブオブジェクトのいずれか、またはその参照型の非静的データメンバーが参照するオブジェクトや関数のいずれかが TU-local であり、かつ定数式で使用可能である場合。
static int tul_var = 1;             // TU-local variable
static int tul_func() { return 1; } // TU-local function
 
int* tul_var_ptr = &tul_var;        // TU-local: pointer to TU-local variable
int (* tul_func_ptr)() = &tul_func; // TU-local: pointer to TU-local function
 
constexpr static int tul_const = 1; // TU-local variable usable in constant expressions
int tul_arr[] = { tul_const };      // TU-local: array of constexpr TU-local object 
struct tul_class { int mem; };
tul_class tul_obj{tul_const};       // TU-local: has member constexpr TU-local object

[編集] 露出 (Exposures)

宣言 D がエンティティ E を名前解決するのは、以下のいずれかの場合です。

  1. D がそのクロージャ型が E であるラムダ式を含む場合。
  2. E が関数または関数テンプレートではなく、D が E を示す id-式、型指定子、ネストされた名前指定子、テンプレート名、またはコンセプト名を含む場合、または
  3. E が関数または関数テンプレートであり、D が E を名前解決する式、または E を含むオーバーロードのセットを参照する id-式を含む場合。
// lambda naming
auto x = [] {}; // names decltype(x)
 
// non-function (template) naming
int y1 = 1;                      // names y1 (id-expression)
struct y2 { int mem; };
y2 y2_obj{1};                    // names y2 (type-specifier)
struct y3 { int mem_func(); };
int y3::mem_func() { return 0; } // names y3 (nested-name-specifier)
template<typename T> int y4 = 1;
int var = y4<y2>;                // names y4 (template-name)
template<typename T> concept y5 = true;
template<typename T> void func(T&&) requires y5<T>; // names y5 (concept-name)
 
// function (template) naming
int z1(int arg)    { std::cout << "no overload"; return 0; }
int z2(int arg)    { std::cout << "overload 1";  return 1; }
int z2(double arg) { std::cout << "overload 2";  return 2; }
 
int val1 = z1(0); // names z1
int val2 = z2(0); // names z2 ( int z2(int) )

宣言が露出であるのは、それが TU-local エンティティを名前解決する場合であり、ただし以下のものを除く場合です。

  1. 非インライン関数または関数テンプレートの関数本体 (ただし、プレースホルダー型を使用する宣言された戻り型を持つ関数の (おそらくインスタンス化された) 定義の推論された戻り型は除く)。
  2. 変数または変数テンプレートの初期化子 (ただし、変数の型は除く)。
  3. クラス定義内のフレンド宣言、および
  4. odr-useではない定数式で初期化された、内部リンケージまたはリンケージのない非揮発性 const オブジェクトまたは参照へのすべての参照。

または、TU-local 値で初期化された constexpr 変数を定義する場合。

[編集] TU-local 制約

モジュールインターフェース単位 (プライベートモジュールフラグメント (もしあれば) の外) またはモジュールパーティション内の非 TU-local エンティティの (おそらくインスタンス化された)宣言、またはその推論ガイドが露出である場合、プログラムは不適格です。他のコンテキストでのそのような宣言は非推奨です。

ある翻訳単位に現れる宣言が、ヘッダー単位ではない別の翻訳単位で宣言された TU-local エンティティを名前解決する場合、プログラムは不適格です。テンプレート特殊化のためにインスタンス化された宣言は、特殊化のインスタンス化の点に現れます。

[編集]

翻訳単位 #1

export module A;
static void f() {}
inline void it() { f(); }         // error: is an exposure of f
static inline void its() { f(); } // OK
template<int> void g() { its(); } // OK
template void g<0>();
 
decltype(f) *fp;                             // error: f (though not its type) is TU-local
auto &fr = f;                                // OK
constexpr auto &fr2 = fr;                    // error: is an exposure of f
constexpr static auto fp2 = fr;              // OK
struct S { void (&ref)(); } s{f};            // OK: value is TU-local
constexpr extern struct W { S &s; } wrap{s}; // OK: value is not TU-local
 
static auto x = []{ f(); }; // OK
auto x2 = x;                // error: the closure type is TU-local
int y = ([]{ f(); }(), 0);  // error: the closure type is not TU-local
int y2 = (x, 0);            // OK
 
namespace N
{
    struct A {};
    void adl(A);
    static void adl(int);
}
void adl(double);
 
inline void h(auto x) { adl(x); } // OK, but a specialization might be an exposure

翻訳単位 #2

module A;
void other()
{
    g<0>();                  // OK: specialization is explicitly instantiated
    g<1>();                  // error: instantiation uses TU-local its
    h(N::A{});               // error: overload set contains TU-local N::adl(int)
    h(0);                    // OK: calls adl(double)
    adl(N::A{});             // OK; N::adl(int) not found, calls N::adl(N::A)
    fr();                    // OK: calls f
    constexpr auto ptr = fr; // error: fr is not usable in constant expressions here
}
English 日本語 中文(简体) 中文(繁體)