我以为我理解static_assert
是如何运作的。但是当我在g ++编译器上尝试这个时,我开始怀疑:
#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
失败。
这在g ++(5.4.0)和clang(3.9.1)上失败,但在VC ++ 2015上工作。
这是缺陷还是我错过了什么?
答案 0 :(得分:4)
写.method public hidebysig instance float64
Abs() cil managed
{
// Code size 47 (0x2f)
.maxstack 8
//000052: return Math.Sqrt(X * X + Y * Y + Z * Z);
IL_0000: ldarg.0
IL_0001: call instance float64 CPUTests.Point3dProperties::get_X()
IL_0006: ldarg.0
IL_0007: call instance float64 CPUTests.Point3dProperties::get_X()
IL_000c: mul
IL_000d: ldarg.0
IL_000e: call instance float64 CPUTests.Point3dProperties::get_Y()
IL_0013: ldarg.0
IL_0014: call instance float64 CPUTests.Point3dProperties::get_Y()
IL_0019: mul
IL_001a: add
IL_001b: ldarg.0
IL_001c: call instance float64 CPUTests.Point3dProperties::get_Z()
IL_0021: ldarg.0
IL_0022: call instance float64 CPUTests.Point3dProperties::get_Z()
IL_0027: mul
IL_0028: add
IL_0029: call float64 [mscorlib]System.Math::Sqrt(float64)
IL_002e: ret
} // end of method Point3dProperties::Abs
.method public hidebysig specialname instance float64
get_X() cil managed
{
// Code size 7 (0x7)
.maxstack 8
//000016: get { return _x; }
IL_0000: ldarg.0
IL_0001: ldfld float64 CPUTests.Point3dProperties::_x
IL_0006: ret
} // end of method Point3dProperties::get_X
只是形象不对,因为它与[temp.res]发生冲突:
如果出现以下情况,该程序格式错误,无需诊断:
- 无法为模板内的static_assert(false)
语句(6.4.1)的模板或子语句生成有效的专业化,并且模板未实例化
您可以将其视为 - 因为constexpr if
的常量表达式不依赖,编译器可以立即看到它的格式错误并触发。
您可以不为该专业化提供static_assert
的定义,或者您可以执行以下操作:
fn()
即使没有人应该专门化template <class T> struct always_false : std::false_type { };
static_assert(always_false<some_dependent_type>::value, "...");
,这也会使得生成有效的专业化成为可能。