提问人:Alexey Starinsky 提问时间:11/18/2023 更新时间:11/18/2023 访问量:57
T 不是非类型模板参数的有效类型
T is not a valid type for non-type template parameter
问:
无法编译以下代码:
#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;
template <class T, class ReturnType>
class func_getter
{
public:
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)();
}
private:
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;
}
// All the code above compiles, but the code below does not.
{
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;
}
MSVC 2022 错误:
error C2993: 'Getter': is not a valid type for non-type template parameter 'state'
答:
4赞
user12002570
11/18/2023
#1
问题是 (aka ) 不是结构类型,因此它不能用作 temp.param 的非类型模板参数:Getter
func_getter<A, int>
- 非类型模板参数应具有以下类型之一(可能是 cv 限定的):
- 结构类型(见下文),
- 结构类型是以下类型之一:
- 具有以下属性的文本类类型:
- 所有基类和非静态数据成员都是公共的、不可变的,并且
(强调我的)
并且由于具有私有非静态数据成员,因此它违反了上述规则,因此不是结构类型,不能用作非类型模板参数。Getter
m_p
3赞
Jean-Baptiste Yunès
11/18/2023
#2
完整的错误是:
template <class T, T state>
^
pp.cpp:65:9: note: while substituting prior template arguments into non-type template parameter 'state' [with T = func_getter<A, int>]
stateless<Getter, g> s;
^~~~~~~~~~~~~~~~~~~~
pp.cpp:44:15: note: 'func_getter<A, int>' is not a structural type because it has a non-static data member that is not public
MyFuncPtr m_p;
重要的一点是“func_getter<A,int>”不是结构类型
。
结构类型不能有私有字段。
2赞
Caleth
11/18/2023
#3
G++ 的错误消息在这里更有用:
error: 'func_getter<A, int>' 不是模板非类型参数的有效类型,因为它不是结构化的。
cppreference 列出要求
非类型模板参数必须具有结构类型,该类型是以下类型之一(可选 cv 限定,将忽略限定符):
- 左值引用类型(对象或函数);
- 整数类型;
- 指针类型(指向对象或函数);
- 指向成员类型(成员对象或成员函数)的指针;
- 枚举类型;
std::nullptr_t
;- 浮点类型;
- 具有以下属性的文本类类型:
- 所有基类和非静态数据成员都是公共的、不可变的,并且
- 所有基类和非静态数据成员的类型都是结构类型或(可能是多维)数组。
即问题是.MyFuncPtr m_p;
private
评论
Getter
func_getter<A, int>
std::array
std::array
std::array::data()