是否有一些忍者技巧可以在声明后将变量设为常量?

发布于 2024-09-18 10:21:14 字数 718 浏览 11 评论 0原文

我知道答案是 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 的解决方案是可以接受的。

编辑:另一个不太抽象的例子,就是让我问这个问题的:

void OpenFile(string path)
{
    boost::to_lower(path);
    // I want path to be constant now
    ifstream ...
}

编辑:另一个具体的例子:重新捕获并行部分中变量的常量

I know the answer is 99.99% no, but I figured it was worth a try, you never know.

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.
}

I can do something somewhat similar with const int b = a;, but it's not really the same and it creates a lot of confusion. A C++0x-only solution is acceptable.

EDIT: another less abstracted example, the one that made me ask this question:

void OpenFile(string path)
{
    boost::to_lower(path);
    // I want path to be constant now
    ifstream ...
}

EDIT: another concrete example: Recapture const-ness on variables in a parallel section.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

羁绊已千年 2024-09-25 10:21:15

一种解决方案是将所有突变代码分解为 lambda 表达式。在 lambda 表达式中执行所有突变,并将结果分配给方法范围内的 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();
  ...
}

或者甚至

void SomeFunction(const int p1) { 
  const int a = [&]() {
    int a = p1;
    a *= 50;
    a %= 10;
    if(example())
       a = 0;
    ..
    return a;
  }();
  ...
}

One solution would be to factor all of the mutation code into a lambda expression. Do all of the mutation in the lambda expression and assign the result out to a const int in the method scope. For example

void SomeFunction(const int p1) { 
  auto calcA = [&]() {
    int a = p1;
    a *= 50;
    a %= 10;
    if(example())
       a = 0;
    ..
    return a;
  };
  const int a = calcA();
  ...
}

or even

void SomeFunction(const int p1) { 
  const int a = [&]() {
    int a = p1;
    a *= 50;
    a %= 10;
    if(example())
       a = 0;
    ..
    return a;
  }();
  ...
}
在你怀里撒娇 2024-09-25 10:21:15

您可以将生成 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);
  // ....
}

否则,没有好的方法可以在编译时执行此操作。

You could move the code to generate a into another function:

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);
  // ....
}

Otherwise, there's no nice way to do this at compile time.

孤者何惧 2024-09-25 10:21:15

我曾经使用的一种模式是用 _ “隐藏”参数,因此代码变为

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.
}

You can also use only const variables 并创建一个函数来计算 a 的新值(如果需要)。我更倾向于不“重用”变量,并尽可能使我的变量不可变:如果您更改某些值,则给它一个新名称。

void SomeFunction(const int _a)
{
    const int a = preprocess(_a);
    ....

}

A pattern I used to use is to "hide" the argument with an _, so the code becomes

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.
}

You could also use only const variables and make a function to compute the new value of a, if necessary. I tend more en more to not "reuse" variables en make as much as possible my variables immutable : if you change the value of something , then give it a new name.

void SomeFunction(const int _a)
{
    const int a = preprocess(_a);
    ....

}
他不在意 2024-09-25 10:21:15

为什么不将代码重构为两个单独的函数。一个返回修改后的 a ,另一个则处理该值(不更改它)。

您也可以将您的对象包裹在持有者类对象周围并使用此持有者。

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&

Why not refactor your code in to two separate functions. One that returns a modified a and another that works on this value (without ever changing it).

You could possibly wrap your object too around a holder class object and work with this holder.

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
}

Your example has an easy fix: Refactoring.

// 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&
久夏青 2024-09-25 10:21:15

如果您只是想避免使用另一个名称,这可能是一种方法。我建议你在使用这个之前三思而后行。

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
}

this might be one way to do it, if you are just trying to avoid another name. i suggest you think twice before using this.

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
}
把昨日还给我 2024-09-25 10:21:15

我实际上并不建议这样做,但您可以使用创意变量阴影来模拟您想要的东西:

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.
    }
}

I don't actually suggest doing this, but you could use creative variable shadowing to simulate something like what you want:

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.
    }
}
绝影如岚 2024-09-25 10:21:15

答案非常可靠,但老实说,我真的想不出使用它的好情况。但是,如果您想预先计算一个常数,这基本上就是您正在做的事情,您有几种主要方法可以做这。

首先我们可以进行以下操作。因此编译器会简单地为我们设置 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.
}

Answers were pretty solid, but honestly I can't really think of a GOOD situation to use this in. However in the event you want to Pre-Calculate a constant which is basically what you are doing you have a few main ways You can do this.

First we can do the following. So the compiler will simply set CompileA# for us in this case it's 50, 100, and 150.

const int CompileA1 = EarlyCalc(1);
const int CompileA2 = EarlyCalc(2);
const int CompileA3 = EarlyCalc(3);

int EarlyCalc(int a)
{
    a *= 50;
    return a;
}

Now anything beyond that there's so many ways you can handle this. I liked the suggestion as someone else had mentioned of doing.

void SomeFunc(int a)
{
    const int A = EarlyCalc(a);
    //We Can't edit A.
}

But another way could be...

SomeFunc(EarlcCalc(a));

void SomeFunc(const int A)
{
    //We can't edit A.
}

Or even..

SomeFunction(int a)
{
    a *= 50;
    ActualFunction(a);
}

void ActualFunction(const int A)
{
    //We can't edit A.
}
冬天的雪花 2024-09-25 10:21:15

当然,在 C++ 中没有办法使用相同的变量名来做到这一点。

Sure, there is no way to do it using the same variable name in C++.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文