未调用模板参数的静态断言

时间:2017-04-10 05:27:37

标签: c++ templates

假设这两个辅助结构:

struct A { static constexpr bool Value = false; };
template <bool DEFERRED> struct B { static_assert(DEFERRED, "Failed"); };

以下使用它的课程:

class XYZ {
public:
    template <class X = A, class Y = B<X::Value>> int SomeFunction() {...}

....
int main() {
    XYZ xyz;
    xyz.SomeFunction();
}

我不明白为什么不调用静态断言,因为模板boolean DEFERRED应该求值为false。但是,当我在函数体内实例化模板类型Y时,会调用静态断言。

有没有办法在不实例化模板类型Y的情况下触发static_assert评估? (或者更容易/更聪明的方式)

编辑:我应该提到我正在使用GCC 5.0

谢谢。

3 个答案:

答案 0 :(得分:1)

您可以将一个类视为对象的蓝图,您可以将模板视为一个类的蓝图。

模板只是一个模板,在将模板实例化为类之前,它不是一个类,在声明xyz变量之前,您不会这样做。

答案 1 :(得分:1)

因为模板布尔值DEFERRED应该评估为false(在您的问题中) ....

这是因为constexpr中的struct A

constexpr说明符可以在编译时评估bool

取出constexpr并构建,你会发现差异。

为什么static_assert无效:

static_assert需要bool_constexpr

DEFERRED只是bool,只有在实例化时才会在模板类体内知道该值。

尝试使用以下代码,我在bool constexpr命名struct B内添加了另一个test。并将该变量传递给static_assert。现在你的static_assert正常工作。

//g++  5.4.0

#include <iostream>

struct A { static constexpr bool Value = false; };
template <bool DEFERRED> struct B { 
    static constexpr bool test =  false;
     static_assert(test, "Failed");
};

class XYZ {
public:
    template <class X = A, class Y = B<X::Value>> int SomeFunction()
    {
        return 0;
    }
};


int main()
{
    XYZ xyz;
    xyz.SomeFunction();
}

你会注意到输出:

source_file.cpp:8:6: error: static assertion failed: Failed
      static_assert(test, "Failed");
      ^

现在将test中的struct B值更改为true

它有效,没有错误。

还有另一种情况,将DEFERRED分配给test变量,如下所示:

template <bool DEFERRED> struct B { 
    static constexpr bool test =  DEFERRED;
     static_assert(test, "Failed");
};

上面说的static_assert只有在main()实例化时才有效,如下所示。

B<false> b;

答案 2 :(得分:0)

我认为我的问题被误解了。我的问题是我期望编译器在实例化类型时评估主体,而不是在声明中使用它时。无论哪种方式,我通过执行以下操作解决了我的问题(使用样板代码):

template <bool DEFERRED> struct B {
    static constexpr bool Proxy = DEFERRED;
    static_assert(Proxy , "Failed");
};
template <class X = A, bool T = B<X::Value>::Proxy> int SomeFunction() {...}

这迫使编译器评估主体并触发任何静态断言。