问题描述
我以为我了解 static_assert 的工作方式。但是,当我在g ++编译器上尝试此操作时,我开始怀疑:
I'm thought I understood how a static_assert worked. But when I tried this on a g++ compiler, I started to wonder:
#include <iostream> #include <type_traits> #define ENABLE_IF(...) std::enable_if_t<__VA_ARGS__, int> = 0 template<typename...Ts> struct list{}; template<typename...Ts> struct is_one_of; template<template <typename...> class TT, typename T, typename T1, typename...Ts> struct is_one_of<T, TT<T1, Ts...>> : is_one_of<T, TT<Ts...>> {}; template<template <typename...> class TT, typename T, typename...Ts> struct is_one_of<T, TT<T, Ts...>> : std::true_type {}; template<template <typename...> class TT, typename T> struct is_one_of<T, TT<>> : std::false_type {}; template<typename...Ts> struct X; template<typename P, typename T, typename...Ts> struct X<P, T, Ts...> : X<P, Ts...> { using X<P, Ts...>::fn; template<typename R, ENABLE_IF(std::is_same<T, R>::value)> constexpr auto fn(R&& x) { return x; } }; template<template <typename...> class TT, typename...Ts> struct X<TT<Ts...>> { template<typename R, ENABLE_IF(!is_one_of<R, TT<Ts...>>::value)> constexpr auto fn(R&& x) { static_assert(false, "Type R didn't match"); } }; template<typename...Ts> struct XX : X<list<Ts...>, Ts...> {}; int main() { XX<int, float> x; std::cout << x.fn(int(3)) << std::endl; return 0; }
现在我本以为不会有任何基础 X< TT< Ts ...> 类型可以被实例化,因为它从未被调用过。通过这种推理,它不会导致 static_assert 失败。
Now I would have thought that there wouldn't be any way that the base type X<TT<Ts...>> could have ever been instantiated because it is never called. And through this reasoning, it should not cause a static_assert failure.
这在g ++(5.4.0)上失败和clang(3.9.1),但在VC ++ 2015上工作。
This fails on g++ (5.4.0) and clang (3.9.1) but worked on VC++ 2015.
这是缺陷还是我遗漏了某些东西?
Is this a defect or am I missing something?
推荐答案
写 static_assert(false)只是形式不正确,因为它违反了[temp.res]:
Writing static_assert(false) is simply ill-formed, because it runs afoul of [temp.res]:
您可以将其视为-由于 static_assert 的常量表达式不依赖,编译器可以立即看到它是错误的-形成并射击。
You can think of it as - since the static_assert's constant expression isn't dependent, the compiler can just immediately see that it's ill-formed and fire.
您可以不提供 fn()$ c $的定义c>进行该专业化,或者您可以执行以下操作:
You can either just not provide a definition of fn() for that specialization, or you could do something like:
template <class T> struct always_false : std::false_type { }; static_assert(always_false<some_dependent_type>::value, "...");
假设即使没有人可以进行专业化,这也可能产生有效的专业化 always_false 。
This would make it hypothetically possible for a valid specialization to be generated, even if nobody should ever specialize always_false.
这篇关于如果未实例化成员模板,是否要评估static_asserts?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!