Why static_assert in template gives me different result with equivalent expressions?

六月ゝ 毕业季﹏ 提交于 2019-12-18 09:04:22

问题


I've noticed strange behavior of static_assert:

#include <iostream>

template <typename T, unsigned int D> struct Vec
{
    static_assert(D && 0, "Invalid dimension for vector!");
};

template <typename T> struct Vec<T, 1>             {union {T x, r;};};
template <typename T> struct Vec<T, 2> : Vec<T, 1> {union {T y, g;};};
template <typename T> struct Vec<T, 3> : Vec<T, 2> {union {T z, b;};};
template <typename T> struct Vec<T, 4> : Vec<T, 3> {union {T w, a;};};

int main()
{
    Vec<float, 3> v;
    v.x = 1;
    v.y = 2;
    v.z = 3;

    return 0;
}

It compiles fine: http://ideone.com/wHbJYP . I would expect

static_assert(0, "Invalid dimension for vector!");

to give me same result, but it causes static assertion failure: http://ideone.com/UEu9Kv . Is gcc correct in both cases? If so, why? Or is it a gcc bug? Then, in which case gcc is correct?


回答1:


§14.6 [temp.res]/p8:

If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

In both cases no valid specialization can be generated for the primary template due to the static_assert (D && 0 is never true no matter the value of D). Since no diagnostic is required, the compiler is free to diagnose one (when you use 0) but not the other (when you use D && 0).

Workaround:

template <unsigned int D> struct always_false : std::false_type {};

template <typename T, unsigned int D> struct Vec
{
    static_assert(always_false<D>::value, "Invalid dimension for vector!");
};

The compiler can no longer reject this at definition time, as there might be an explicit specialization of always_false whose value member is true.




回答2:


Everything is not 1,2,3,4 (for which specific specializations exist) will go into the "master" definition, that have to assert for every value of D it will be called.

So you need an expression that contains D and that is always false, to cause the compiler to evaluate it in dependency of D

If you just use 0, it will be anymore dependent and the compiler will evaluate as it matches during parsing, causing the assertion to always take place. Even if it will not be the class you will instantiate.



来源:https://stackoverflow.com/questions/27867949/why-static-assert-in-template-gives-me-different-result-with-equivalent-expressi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!