You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSVC 2022编译报错:Getter并非非类型模板参数的有效类型

非类型模板参数编译错误分析与解决

问题描述

给定代码中,stateless<Array, a>和stateless<A, a>可以正常编译,但使用func_getter作为非类型模板参数时,MSVC 2022报错:

error C2993: 'Getter': is not a valid type for non-type template parameter 'state'

错误原因

C++标准对非类型模板参数的类型有严格限制:只有结构类型(structural type)的constexpr对象才能作为非类型模板参数传递。

结构类型需满足以下全部条件:

  • 是标量类型(如int、指针、成员指针),或
  • 是类类型且满足:
    • 所有非静态数据成员为公共访问权限
    • 无用户声明的析构函数
    • 无私有/保护的非静态数据成员
    • 无基类
    • 无虚函数
    • 所有非静态数据成员的类型都是结构类型或结构类型的数组

你的func_getter类包含私有成员m_p,违反了"所有非静态数据成员为公共访问权限"的要求,因此不属于结构类型,无法作为非类型模板参数的类型。

而std::array和struct A都是结构类型:

  • std::array的内部成员符合标准规定的公共访问要求
  • struct A的x是公共成员,无私有/保护成员,满足结构类型条件

解决方案

调整func_getter的定义,使其符合结构类型要求,最简单的方式是将成员设为公共访问权限:

#include <array>

template <class T, T state>
class stateless
{
public:
    void f() { /* do something with m_val*/; }
private:
    static inline constexpr T m_val = state;
};

struct A
{
    int x;
    int GetX() const { return x; }
};

template <class T, class ReturnType>
using FuncPtr = ReturnType(T::*)() const;

// 改为struct(默认成员public),或显式将m_p设为public
template <class T, class ReturnType>
struct func_getter
{
    using object_type = T;
    using value_type = ReturnType;
    using MyFuncPtr = FuncPtr<T, ReturnType>;

    constexpr func_getter(MyFuncPtr p) : m_p(p) {}

    constexpr ReturnType operator() (const T& val) const
    {
        return (val.*m_p)();
    }

    MyFuncPtr m_p; // 公共成员
};

int main()
{
    {
        using Array = std::array<int, 3>;
        constexpr std::array<int, 3> a = { 1, 2, 3 };
        stateless<Array, a> s;
    }

    {
        constexpr A a = { 1 };
        stateless<A, a> s;
    }

    {
        using Getter = func_getter<A, int>;
        constexpr Getter g(&A::GetX);
        stateless<Getter, g> s; // 编译通过
    }

    {
        constexpr func_getter g(&A::GetX);
        stateless<decltype(g), g> s; // 编译通过
    }

    return 0;
}

修改说明

  • 将func_getter从class改为struct,利用struct默认的公共成员访问权限;也可以保留class,但显式给m_p加上public修饰符。
  • 修改后func_getter满足结构类型的所有要求,其constexpr实例即可作为非类型模板参数传递。

内容的提问来源于stack exchange,提问作者Alexey Starinsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:01:11