为 bitset 模板参数调用 constexpr 函数

Calling constexpr function for bitset template parameter

我正在尝试键入 std::bitset class 的别名,其中模板参数 N 是使用 constexpr 函数计算的。不过,这种做法好像是运行撞墙了。

代码目前如下所示:

static constexpr std::size_t ComponentCount() noexcept {
    return 3U;
}

static constexpr std::size_t TagCount() noexcept {
    return 5U;
}

using Bitset = std::bitset<ComponentCount() + TagCount()>;

我收到的错误如下:

1>error C2975: '_Bits': invalid template argument for 'std::bitset', expected compile-time constant expression
1>  note: see declaration of '_Bits'

感谢您的帮助。

如@MattWeber 的评论所述,使用当前 webcompiler.cloudapp.net 和编译器版本 19.00.23720.0(2016 年 1 月 20 日构建)这个使用您的代码的小测试程序

int main()
{
   cout << Bitset{}.size() << "\n";
}

确实输出 8。所以只需获取最新的 Visual Studio 并检查编译器版本(如果它大于 19.00.23720.0,它应该可以工作)。

事实证明,我在最初的问题中没有包含足够的上下文。问题最终变得更加微妙。

下面是我的代码的更准确的表示:

template
<
    typename ComponentList,
    typename TagList,
    typename SignatureList
>
struct Settings {
    // ...

    static constexpr std::size_t ComponentCount() noexcept {
        return 3U;
    }

    static constexpr std::size_t TagCount() noexcept {
        return 5U;
    }

    // ...

    using Bitset = std::bitset<ComponentCount() + TagCount()>;

    // ...
};

这种方法对我来说似乎没问题,并且没有向我提供任何编译器警告或任何东西。只是原问题中提到的编译器错误。

然而,当我进一步简化问题以尝试更准确地隔离问题时,我得到了这个:

struct Settings {
    static constexpr std::size_t ComponentCount() noexcept {
        return 3U;
    }

    static constexpr std::size_t TagCount() noexcept {
        return 5U;
    }

    using Bitset = std::bitset<ComponentCount() + TagCount()>;
};

进行此简化后(或更具体地说,删除模板参数后),VS2015 在 ComponentCount()TagCount() 函数调用中发现错误 function call must have a constant value in a constant expression,并且用红色突出显示它们。显然,编译器无法查看包含在与常量表达式相同的结构中的静态 constexpr 函数?诡异的。它可能试图在定义 const 表达式之前进行类型别名。

模板化结构的解决方案如下:

using ThisType = Settings<ComponentList, TagList, SignatureList>;

// ...

using Bitset = std::bitset<ThisType::ComponentCount() + ThisType::TagCount()>;

但是,这种方法不适用于非模板结构。在这种情况下,请参阅我的其他 了解不同的方法。