答えは99.99%は違いますが、試してみる価値はあると思いました。
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
// From this point on I want to make "a" const; I don't want to allow
// any code past this comment to modify it in any way.
}
const int b = a;
、しかしそれは実際には同じではなく、多くの混乱を引き起こします。 C++ 0xのみのソリューションでも問題ありません。
[〜#〜] edit [〜#〜]:別の抽象化されていない例で、私にこの質問をさせた例:
void OpenFile(string path)
{
boost::to_lower(path);
// I want path to be constant now
ifstream ...
}
[〜#〜] edit [〜#〜]:別の具体的な例: 並列セクションの変数の定数の再取得 =。
1つの解決策は、すべての突然変異コードをラムダ式に因数分解することです。ラムダ式ですべての変更を行い、結果をメソッドスコープのconst int
に割り当てます。例えば
void SomeFunction(const int p1) {
auto calcA = [&]() {
int a = p1;
a *= 50;
a %= 10;
if(example())
a = 0;
..
return a;
};
const int a = calcA();
...
}
コードを移動して、a
を生成して別の関数に入れることができます。
int ComputeA(int a) {
a *= 50;
a %= 10;
if (example())
a = 0;
return a;
}
void SomeFunction(const int a_in) {
const int a = ComputeA(a_in);
// ....
}
それ以外の場合は、コンパイル時にこれを行うための良い方法はありません。
私が使用していたパターンは、_で引数を「隠す」ことなので、コードは
void SomeFunction(int _a)
{
// Here some processing happens on a, for example:
_a *= 50;
_a %= 10;
if(example())
_a = 0;
const int a = _a;
// From this point on I want to make "a" const; I don't want to allow
// any code past this comment to modify it in any way.
}
必要に応じて、const変数のみを使用して、aの新しい値を計算する関数を作成することもできます。変数を "再利用"しないようにする傾向があります。変数をできるだけ不変にします。何かの値を変更した場合は、新しい名前を付けます。
void SomeFunction(const int _a)
{
const int a = preprocess(_a);
....
}
コードを2つの別々の関数にリファクタリングしてみませんか。 1つは変更されたa
を返し、もう1つはこの値を操作します(これを変更することなく)。
オブジェクトをホルダークラスオブジェクトにラップして、このホルダーを操作することもできます。
template <class T>
struct Constify {
Constify(T val) : v_( val ) {}
const T& get() const { return v_; }
};
void SomeFuncion() {
Constify ci( Compute() ); // Compute returns `a`
// process with ci
}
あなたの例には簡単な修正があります:リファクタリング。
// expect a lowercase path or use a case insensitive comparator for basic_string
void OpenFile(string const& path)
{
// I want path to be constant now
ifstream ...
}
OpenFile( boost::to_lower(path) ); // temporaries can bind to const&
これは、別の名前を避けようとしているだけの場合、1つの方法です。これを使用する前に、よく考えることをお勧めします。
int func ()
{
int a;
a %= 10;
const int const_a = a;
#define a const_a
a = 10; // this will cause an error, as needed.
#undef a
}
実際にこれを行うことはお勧めしませんが、クリエイティブな変数シャドウイングを使用して、必要なものをシミュレートできます。
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
{
const int b = a;
const int a = b; // New a, shadows the outside one.
// Do whatever you want inside these nested braces, "a" is now const.
}
}
答えはかなりしっかりしていましたが、正直に言って、これを使用するのに良い状況は本当に考えられません。しかし、基本的にあなたがしていることである定数を事前計算したい場合は、いくつかの主な方法がありますこの。
まず、次のことができます。したがって、この場合、コンパイラーは単にCompileA#を50、100、および150に設定します。
const int CompileA1 = EarlyCalc(1);
const int CompileA2 = EarlyCalc(2);
const int CompileA3 = EarlyCalc(3);
int EarlyCalc(int a)
{
a *= 50;
return a;
}
これを超えると、これを処理する方法が非常に多くなります。他の人が言っているように私は提案が好きだった。
void SomeFunc(int a)
{
const int A = EarlyCalc(a);
//We Can't edit A.
}
しかし、別の方法は...
SomeFunc(EarlcCalc(a));
void SomeFunc(const int A)
{
//We can't edit A.
}
あるいは..
SomeFunction(int a)
{
a *= 50;
ActualFunction(a);
}
void ActualFunction(const int A)
{
//We can't edit A.
}