C++类型漏洞解释
C++ type loophole explanation
愚蠢的问题。谁能向我解释这段代码是如何工作的? (来自这里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++ 允许吗?
更新:
刚刚意识到它取决于编译器甚至编译器版本。
适用于任何 >=8 的 GCC(可能也适用于旧版本)。
不能用 clang >= 10 编译,但可以用 clang 7.0
正常工作
所以我要说我真正的问题是编译器错误还是标准行为?
它导致模板特化的实例化loophole_t<std::string, 0>
。
作为具有 friend
函数的 class 模板(请记住,friend
不是成员),全局命名空间中的 also brings the function into scope。
该函数可以拼写为 std::string loophole(tag<0> unusedParam);
。
除了用 sizeof
之后,它不会直接用于任何其他用途,除了用 decltype
“检索”它的 return 类型并将其与 std::string
在静态断言中(通过演示预计会通过)。
作者在表达式tag<0>
中“存储”了std::string
。有点。
如果你写了更多:
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.
愚蠢的问题。谁能向我解释这段代码是如何工作的? (来自这里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++ 允许吗?
更新: 刚刚意识到它取决于编译器甚至编译器版本。 适用于任何 >=8 的 GCC(可能也适用于旧版本)。 不能用 clang >= 10 编译,但可以用 clang 7.0
正常工作所以我要说我真正的问题是编译器错误还是标准行为?
它导致模板特化的实例化loophole_t<std::string, 0>
。
作为具有 friend
函数的 class 模板(请记住,friend
不是成员),全局命名空间中的 also brings the function into scope。
该函数可以拼写为 std::string loophole(tag<0> unusedParam);
。
除了用 sizeof
之后,它不会直接用于任何其他用途,除了用 decltype
“检索”它的 return 类型并将其与 std::string
在静态断言中(通过演示预计会通过)。
作者在表达式tag<0>
中“存储”了std::string
。有点。
如果你写了更多:
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.