C++ 可变参数模板“不包含参数包”时 constexpr 是否应该避免?

C++ variadic template 'contains no parameter packs' when constexpr if should avoid?

提问人:TBCM 提问时间:9/2/2023 更新时间:9/2/2023 访问量:55

问:

我正在使用一些 c++ 20 功能,例如折叠运算符,以在编译时获得可变参数的大小。然后,如果没有提供模板,我将使用此大小来避免使用任何模板。templateconstexpr ifvariadic template

但是,我仍然收到错误:


src/engine/inb/component.h:39:68: error: expected primary-expression before '>' token
   39 |                 swallowTemplateExpansion(i_addComponent<_Components>(inheritor)...);
      |                                                                    ^
src/engine/inb/component.h:39:80: error: expansion pattern '((((cosmic::ComponentHolder<_Child>*)this)->cosmic::ComponentHolder<_Child>::i_addComponent < <expression error>) > (inheritor))' contains no parameter packs
   39 |                 swallowTemplateExpansion(i_addComponent<_Components>(inheritor)...);
      |                                                                                ^~~

这告诉我编译器无论如何都会计算 else 语句? 避免在编译时编写这样的代码,因此它不应该给我这个错误。constexpr

代码如下:


template<typename _Child>
    struct ComponentHolder
    {
    private:
        std::vector<std::shared_ptr<Component<_Child>>> components{};
        int i_addComponent(_Child* inheritor)
        {
            components.push_back(std::make_shared<Component<_Child>>(inheritor));
            return 0;
        }
    public:
        template<typename... _Components>
        constexpr ComponentHolder(_Child* inheritor)
        {
            constexpr auto _Size = (sizeof(_Components) + ...);
            if constexpr (_Size == 0)
            {
                return;
            } 
            else {
                swallowTemplateExpansion(i_addComponent<_Components>(inheritor)...);
            }
        }
    };

并且只是一个空白的消费者空函数:swallowTemplateExpansion


template<typename... T>
    void swallowTemplateExpansion(T&&... x)
    {}

为什么当我告诉编译器如果它的大小为 0 时,我仍然在尝试解包,不要解包?constexpr ifvariadic templatevariadic template

提前感谢您的任何帮助!

C++ 模板 variadic 模板 constexpr fold

评论

0赞 Guillaume Racicot 9/2/2023
你使用的是 MSVC (Visual studio) 吗?
0赞 Jarod42 9/2/2023
使用 ,订单不保证。使用逗号运算符 () 保证从左到右的顺序。swallowTemplateExpansion(i_addComponent<_Components>(inheritor), ...);

答:

0赞 TBCM 9/2/2023 #1

我通过向函数提供模板参数解决了这个问题,这是一个非常愚蠢的错误。i_addComponent

template<typename _Component>
        int i_addComponent(_Child* inheritor)
        {
            components.push_back(std::make_shared<_Component>(inheritor));
            return 0;
        }