Variadic模板专业化

时间:2014-05-28 17:13:35

标签: c++ templates variadic-templates template-specialization static-assert

所以我尝试使用自定义文字运算符来实现二进制文字。但是,似乎我在模板专业化方面做错了。 static_assert在不应该

的情况下进行评估
template <char... bits>
struct bin_imp
{
        static constexpr unsigned long long to_ull()
        {
                static_assert(false,"not binary value");
                return 0;
        }
};

template <char... bits>
struct bin_imp<'0', bits...>
{
        static constexpr unsigned long long to_ull()
        {
                return bin_imp<bits...>::to_ull();
        }
};

template <char... bits>
struct bin_imp<'1', bits...>
{
        static constexpr unsigned long long to_ull()
        {
                return (1ULL << sizeof...(bits)) | bin_imp<bits...>::to_ull();
        }
};


template <>
struct bin_imp<>
{
        static constexpr unsigned long long to_ull()
        {
                return 0;
        }
};

template <char... bits>
static constexpr unsigned long long operator "" _b ()
{
        return bin_imp<bits...>::to_ull();
};

int main(int argc, char* argv[])
{
        unsigned int i = 11_b;
        return 0;
}

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

static_assert(false,"not binary value");

编译器拒绝这一点,因为即使在解析源代码的第一阶段,编译器显然也会失败。编译器不需要实例化类模板,以便知道static_assert将失败。

这里你可以做的是,强制编译器在解析的第二阶段评估条件 - 即实例化(类模板的)函数。为此,您需要一个类模板,例如:

 template<char ...>
 struct always_false : std::false_type {};

现在将其用作:

static_assert(always_false<bits...>::value,"not binary value");

现在编译器无法评估条件直到它实例化always_false<>,这恰好总是错误。

也就是说,在评估表达式时,解决方案是:懒惰

答案 1 :(得分:3)

由于static_assert独立于模板参数,编译器可以在实例化之前静态断言。

要解决您的问题,您可以使用:

template <char... bits> struct bin_imp;

template <char... bits>
struct bin_imp
{
    static constexpr unsigned long long to_ull() = delete;
};

答案 2 :(得分:-1)

如果第一个参数的计算结果为true,则

static_assert失败(参见this布尔转换部分)

由于您使用的是布尔值false,因此会失败。

由于static_assert不依赖于模板参数,因此编译器会对其进行求值,而与范围无关,因此,断言失败。如果您使用动态断言(#include <cassert>assert(expr)),您将看到代码正常工作。测试:http://rextester.com/live/HCT76663