aik*_*khs 8 c++ templates c++14
我在理解函数(尤其是模板函数和局部变量)在编译期间的行为时遇到了麻烦。
因此,此代码适用于std::get:
enum class UserInfoFields{name, email, address};
using UserInfo = std::tuple<std::string, std::string, std::string>;
int main()
{
UserInfo s{"Edmund", "edmund@page.me", "Denver street 19"};
std::cout << std::get<static_cast<size_t>(UserInfoFields::name)>(s) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解,这是因为std::get它是模板函数,并且需要在编译过程中知道模板参数。这样做很有意义,因为static_cast<...它可以在编译期间为我们提供价值。
我不明白的是,如果我将main()代码更改为此:
int main()
{
UserInfo s{"Edmund", "edmund@page.me", "Denver street 19"};
auto a = static_cast<size_t>(UserInfoFields::name);
std::cout << std::get<a>(s) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是不允许的。我知道我必须使用,constexpr但我想知道为什么第二个代码不起作用?
你写了自己
std::get是模板函数,需要在编译过程中知道模板参数
在一般情况下,编译期间不知道局部变量的值;局部变量的值是运行时属性。因此,局部变量不能用作模板参数。
如果要将其用作一个,则必须将其设为编译时值。这是通过使其实现的constexpr(正如您在问题中已经提到的那样)。
模板非类型参数(如size_t所std::get<>采用的 )必须是编译时常量。
你的auto a不是编译时间常数。a在您的具体情况下,您可以证明此时的值永远不会变化并且始终为0。
但 C++ 是一种强类型语言,依赖于程序员提供的显式类型。在 进行求值时std::get<a>,C++ 允许自己知道的唯一一件事a是它是类型为 的非常量非 constexpr 局部变量std::size_t。
因此,如果std::get<a>有效,那么必须:
int main(int argv, char ** argc) {
UserInfo s{"Edmund", "edmund@page.me", "Denver street 19"};
std::size_t a = argv; // number of arguments
std::cout << std::get<a>(s) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
std::get<std::size_t>是一个nothrow函数,不允许在运行时失败。如果您使用 100 个参数调用此代码,则上面的代码不可能工作。
其次,虽然你UserInfo有 3 个相同的类型,std::get<size_t>(tuple<a,b,c>)但当类型不同时才有效。所以
using UserInfo = std::tuple<int, std::string, double>;
Run Code Online (Sandbox Code Playgroud)
然后std::get< argv >( some_user_info )还得工作。在这种情况下,它返回的类型可以是三种类型中的任何一种——但 C++ 要求所有表达式都具有一种类型。
简短的版本是“语言标准是这样说的”。较长的版本是“在一般情况下,您的代码不起作用”。
现在,您可以通过一些更改来解决特定情况下的代码。
using UserInfo = std::array<std::string, 3>;
Run Code Online (Sandbox Code Playgroud)
现在UserInfo已知有 3 种制服类型。
std::cout << s[a] << std::endl;
Run Code Online (Sandbox Code Playgroud)
现在您传入索引,并且由于参数[]不是模板非类型参数,因此它可以在运行时发生变化。
[]如果索引越界,则允许执行 UB。(std::get<a>不是)。
现在,C++ 可能会发展,新标准可能会带来一些魔力,并以某种方式检测您的特殊情况并允许 std get 在运行时失败等。但是,每次调用都std::get可能是运行时失败,而以前则不然;您的应用程序的测试界面刚刚爆炸。
哎呀,它可以自动检测auto a = blah前一行中使用常量表达式初始化的内容,并使其在下一行中使用自动成为常量表达式。
get_proper_a()但是,如果程序员知道自己在做什么,并且将调用替换为 来进行3调试,那么他们的代码可能会因为秘密类型信息“泄漏”到代码中而虚假地改变行为。当get_proper_a()which 实际返回3(但编译器无法证明)运行时,代码会在运行时中断。