【发布时间】:2020-10-15 13:08:24
【问题描述】:
我正在编写一个小程序,用于将代码从 Go 转换为 C++20 (go2cpp)。大多数代码转换起来相对简单,但我遇到了一种特殊情况,即在解压缩元组时会发生名称冲突。
这是一个完整的例子,可以保存为ie。 main.cpp:
#include <cstdlib>
#include <iostream>
#include <string>
#include <optional>
#include <tuple>
using namespace std::string_literals;
using error = std::optional<std::string>;
// convert a string to a double
// return both the double and an error (optional string)
// this must behave in a simiar fashion to strconv.ParseFloat in Go
auto strconvParseFloat(std::string s, int n) -> std::tuple<double, error>
{
// n is ignored, for now
try {
return std::tuple { std::stod(s), std::nullopt };
} catch (const std::invalid_argument& ia) {
return std::tuple { 0.0, std::optional { "invalid argument"s } };
}
}
// convert a string to an int
// return both the int and an error (optional string)
// this must behave in a simiar fashion to strconv.ParseInt in Go
auto strconvParseInt(std::string, int a, int n) -> std::tuple<int, error>
{
return std::tuple { 0, std::optional { "not implemented"s } };
}
auto isNum(std::string s) -> bool
{
auto [_0, err] = strconvParseFloat(s, 64);
auto isFloat = (err == std::nullopt);
auto [_1, err] = strconvParseInt(s, 0, 64);
auto isInt = (err == std::nullopt);
return isFloat || isInt;
}
auto main(int argc, char** argv) -> int
{
const auto s = "3.14"s;
//const auto s = "asdf"s;
std::cout << s << " is a number: "s << std::boolalpha << isNum(s) << std::endl;
return EXIT_SUCCESS;
}
我使用 GCC 10.2.0 使用这个命令编译它:
g++ -o main -std=c++2a -O2 -pipe -fPIC -fno-plt -fstack-protector-strong -Wall -Wshadow -Wpedantic -Wno-parentheses -Wfatal-errors -Wvla main.cpp
我得到的错误信息是这样的:
main.cpp: In function ‘bool isNum(std::string)’:
main.cpp:36:15: error: conflicting declaration ‘auto err’
36 | auto [_1, err] = strconvParseInt(s, 0, 64);
| ^~~
如果我将第一个 err 重命名为 err1 并将第二个 err 重命名为 err2,则程序编译并运行得很好。
如何强制或以其他方式让 C++ 编译器相信 err 在 auto [_1, err] 中的第二次使用是可以的(就像它在 Go 中的使用方式一样),并且我希望重新声明 err?有没有我可以使用的编译器指令,或者std::tie 以某种方式与std::ignore 结合使用?
我怀疑在这种情况下我必须使用命名空间,但我更愿意找到另一种方式,在从 Go 自动转换代码时,不必跟踪该块中的内容。
【问题讨论】:
-
很高兴看到您正在学习 c++ :) 将来,除了语言版本标签之外,请确保始终使用 c++ 标签,更多人会以这种方式看到您的问题。
-
@cigien,每个使用 c++ 的人都在学习 c++。 :) 但是,如果部分代码没有缩进自动生成,我不会以类似的方式编写代码。以后记得加c++标签,不只是c++17和c++20。
-
哦,对不起,我只是假设你主要习惯于
go基于这个问题。你说得对,在 C++ 中总有一些东西要学:) -
您可以考虑立即调用 lambda 函数来初始化
isFloat和isInt,从而使 lambda 内部的_0/1和err局部变量不会泄漏到函数范围。或者甚至只是做类似const bool isFloat = !std::get<1>(strconvParseFloat(s, 64));