首页 > 解决方案 > C++类型漏洞解释

问题描述

愚蠢的问题。谁能向我解释一下这段代码是如何工作的?(从这里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++ 允许使用 at 吗?

更新:刚刚意识到它取决于编译器甚至编译器版本。适用于任何 >=8 的 GCC(可能也适用于旧版本)。不使用 clang >= 10 编译,但使用 clang 7.0 可以正常工作

所以我会说我真正的问题是编译器错误还是标准行为?

标签: c++c++14

解决方案


它会导致模板专业化的实例化loophole_t<std::string, 0>

作为具有friend函数的类模板(请记住,friends 不是成员),这也将函数带入全局命名空间的范围内。

那个函数可以拼写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>;

…然后使用更惯用的方法来提取类型N


推荐阅读