愚蠢的问题。谁能向我解释一下这段代码是如何工作的? (从这里 https://alexpolt.github.io/type-loophole.html )
#include <string>
#include <type_traits>
template<int N> struct tag{};
template<typename T, int N>
struct loophole_t {
friend auto loophole(tag<N>) { return T{}; };
};
auto loophole(tag<0>);
int main() {
sizeof( loophole_t<std::string, 0> );
static_assert(std::is_same< std::string, decltype( loophole(tag<0>{}) ) >::value);
}
它看起来像 sizeof( loophole_t<std::string, 0> );
影响编译器全局状态。我的意思是如果我们删除这一行 static_asserts
失败。在 C++ 中允许吗?更新:
刚刚意识到这取决于编译器甚至编译器版本。
适用于任何 GCC >=8(可能也适用于旧版本)。
不能用 clang >= 10 编译,但在 clang 7.0 下工作正常
所以我想说我真正的问题是编译器错误还是标准行为?
最佳答案
它导致模板特化的实例化 loophole_t<std::string, 0>
.
作为带有 friend
的类模板函数(记住, friend
不是成员),即 also brings the function into scope在全局命名空间中。
该函数可以拼写为 std::string loophole(tag<0> unusedParam);
.
除了扔掉之外,它不直接用于任何其他用途 sizeof
在那之后,除了用 decltype
“检索”它的返回类型。并将其与 std::string
进行比较在静态断言中(通过演示,预计会通过)。
作者已“收藏”std::string
在表达式 tag<0>
中.有点。
如果你写了更多:
sizeof( loophole_t<std::string, 0> );
sizeof( loophole_t<int, 1> );
sizeof( loophole_t<char, 2> );
......你最终会在范围内得到一大堆函数,它们可以拼写:std::string loophole(tag<0> unusedParam);
int loophole(tag<1> unusedParam);
char loophole(tag<2> unusedParam);
……现在你可以看到函数声明为每个标签“存储”了一个类型。我们可以使用标签“访问”类型:decltype(loophole(tag<0>{})) thisIsAString = "lol";
decltype(loophole(tag<1>{})) thisIsAnInt = 42;
decltype(loophole(tag<2>{})) thisIsAChar = '!';
这有什么实际好处,我不知道。但是,如果您对此感到绝望,则可以:using MyTypes = std::tuple<std::string, int, char>;
...然后使用 somewhat more idiomatic means to extract type N .
关于C++类型漏洞解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65190015/