有办法将“模式匹配”到一个变量名中吗?

huangapple go评论88阅读模式
英文:

Is there a way to "pattern match" into a variable name?

问题

I apologize in advance, this is going to be a goofy question but I don't know how to word a google search well enough to get a response for this.

Now I've been occasionally thinking about this, every time it would've made my code easier to write if it existed, let's say I have two vectors: vec0<int> and vec1<int>. (for the sake of the example).

Is there any way of doing something similar to the lines of the code below? Let's say we want to push the even numbers into vec0 and the odd numbers into vec1. It should look something like this

for(int i=0;i<=n;i++)
turnStringIntoVariable(f"vec{i%2}").push_back(i)

So a function would compute the name of the variable and fetch its address, then you can perform operations on the result.

Does anything like this exist in practice? This is out of sheer curiosity, really.

英文:

I apologize in advance, this is going to be a goofy question but I don't know how to word a google search well enough to get a response for this.

Now I've been occasionally thinking about this, every time it would've made my code easier to write if it existed, let's say I have two vectors: vec0&lt;int&gt; and vec1&lt;int&gt;. (for the sake of the example).

Is there any way of doing something similar to the lines of the code below? Let's say we want to push the even numbers into vec0 and the odd numbers into vec1. It should look something like this

for(int i=0;i&lt;=n;i++)
turnStringIntoVariable(f&quot;vec{i%2}&quot;).push_back(i)

So a function would compute the name of the variable and fetch its address, then you can perform operations on the result.

Does anything like this exist in practice? This is out of sheer curiosity, really.

答案1

得分: 4

这在C++中是不可能做到的。在C++的核心语言层面,无论是在运行时还是在编译时,都没有将字符串转换为相应符号(例如引用变量)的方法。

在预处理器阶段,在编译时有一些类似的支持,但不支持你所期望的语法。

就像你展示的运行时情况一样,这在根本上是不可能的,因为C++是静态类型的,因此表达式的类型不能依赖于运行时的值,实体的名称是C++中的纯编译时概念,它们在运行时不存在(实际上,变量本身也不存在)。

如果你想在C++中将字符串映射到变量,你需要显式提供一对一的映射,例如作为std::map<std::string, /*共享变量类型*/>或编写一个包含映射作为控制流一部分的函数。

但几乎可以确定这种方法是低效的,例如,在你的示例中,你可能真的想要使用类似可变模板(variadic template)或fold表达式,以重复应用i和变量对表达式。你应该研究模板(特别是可变模板)和使用元组的std::apply以及std::index_sequence的常见习惯用法,以生成与模板参数包中元素对应的编译时数字序列,以便它们可以在fold表达式中一起使用。

或者,只要你的vecX都具有相同的类型,就不需要像模板那样复杂的东西。一个简单的数组就足够了:

std::array<std::reference_wrapper<std::vector<int>>, 3> vecs = {std::ref(vec1), std::ref(vec2), std::ref(vec3)};
for(int i=0; i<vecs.size(); i++)
    vecs[i].get().push_back(i);
英文:

This is impossible to do in C++. There is no way to turn a string into a corresponding symbol (e.g. referring to a variable) at the C++ core language level either at run time or at compile time.

There is limited support for something similar at compile time in the preprocessor stage, but not with syntax like you want.

At run time like you are showing, it is fundamentally impossible, because C++ is statically-typed, so that the type of an expression cannot depend on run time values and because names of entities are pure compile-time concepts in C++. They don't exist at run time (and neither do variables themselves, really).

If you want to map strings to variables in C++, you need to provide the mapping one-to-one explicitly e.g. as a std::map&lt;std::string, /*shared type of variables*/&gt; or by writing a function that contains the mappings explicitly as part of the control flow.

But that is almost surely inefficient and e.g. in your example, you would really want to use something like a variadic template or a fold expression that applies pairs of i and variable to the expression repeatedly. The topic you should look at are templates (especially variadic ones) and common idioms like those using std::apply with tuples and std::index_sequence to generate compile-time numeric sequences corresponding to elements of template parameter packs so that they can be used together in fold expressions.

Or, as long as all your vecX have the same type, nothing as fancy as templates is even required. A simple array is enough:

std::array vecs = {std::ref(vec1), std::ref(vec2), std::ref(vec3)};
for(int i=0;i&lt;vecs.size();i++)
    vecs[i].get().push_back(i);

huangapple
  • 本文由 发表于 2023年3月4日 04:49:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631751.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定