2

クラスがTあり、このコードをコンパイルしないようにしたい:

void PassByValue(T);

ただし、これらすべてを許可します。

void PassByRefernce(T&);
void PassByPointer(T*);

注:関数が使用または定義されていない場合でも、by値をとる関数を宣言することは違法である(つまり、コンパイルエラーを生成する)ことを望んでいることに注意してください。T


編集:以下は完全に有効なC++であることに注意してください。

class T {
  public:
    T() {}
  private:
    // Prevent copy/assignment
    T(const T&);
    T& operator=(const T&);
};

void Fn(T);  // I want this line to error, even if the function is never used.

int main() { return 0; } 
4

2 に答える 2

4

厳密には可能ではありません (以下を参照)。最善の方法は、そのような関数をコピー不可にして使用不可/定義不可にすることTです。

これは、次のようにコピー ctor を削除することによって行われます。

class T
{
    T(const T&) =delete;
    T& operator=(const T&) =delete;
    .....
};

C++11 を使用できない場合、これらの宣言を非公開にするのと同じ効果が発生します。

class T
{
public:
    .....
private:
    T(const T&);
    T& operator=(const T&);
};

実装は必要ありません。

このように、クラスは別のインスタンスから状態を受け取ることができないため、関数に渡す唯一の方法は、(参照またはポインターを介した) 間接化によるものです。


もちろん、これは元の質問を(文字通り)「解決」しません。

void func(T);

まだ可能です。ただし、その関数を呼び出すことはできないため、T の安全性は認められます。

残念ながら、今日の C++ 言語の定義方法については、「クリーンな」ソリューションは存在しません。

struct A;
void func(A);

コンパイルする必要があります。

コード自体は何もしませんが (いくつかのシンボルを宣言するだけです) 、セマンティクスstruct A;については何も言いません。Aの宣言を否定するにfuncは、完全な宣言を含む、または含む翻訳単位 (CPP ファイル) 内になければなりませんA(そのため、コピーが不可能であることを知ることができます)。しかし、これは、上記のスニペットが含まれているすべての翻訳単位で必ずしも発生するわけではありません。

それができる言語があります。「システム言語ドメイン」にとどまるために、D を考えてみてください。しかし、「完全に宣言する前に使用する」ことを許可する D は、「ソースを含める」のではなく、「モジュールをインポートする」(コンパイラが完全な定義にアクセスできる) 反復変換をサポートします (何かがまだ定義されておらず、後でコンパイラが定義されている場合)。 「洗練」に戻り、一貫したコードに「収束」するまで繰り返すか、矛盾が見つかった場合はコードを拒否します)。また、その「インポート メカニズム」とセマンティック/シンタックスの分離のため、(ほとんどの) C++ にリンクできず、C でコンパイルされたライブラリまたは obj のみを受け入れます。(そしてヘッダーの C から D への変換が必要です!)

C++ 変換パスは、D のような変換パスに進化しますか? 言いにくい。C の「包含モデル」の C 下位互換性を保持する必要がある間は、ほとんどありません。

于 2012-07-11T19:48:38.507 に答える
0

2 つのオプションがあります。コピー コンストラクターを非公開にするか、T 抽象クラスを作成します。

于 2012-07-11T19:49:22.033 に答える