[英]How can I resolve Error: variable template-id 'complex type' in nested-name-specifier
首先,让我们定义问题。 在一个较大的项目中,我们有很多 class 类型。 一堆这些类型是由我们不控制 output 的工具生成的。 这意味着我们无法控制它们的 inheritance 链,它们的实现可能非常复杂。 还有现有的工具可以使用宏智能地推出这些类型,以构建复杂的结构,例如复杂的 switch case 语句,以及模板无法解决的其他重复实现。 但我希望尽可能地增加类型系统的弹性和安全性。 因此,我还希望能够利用 TypeLists 和带有 static 断言的 type_traits 来限制具有清晰可读的错误消息的某些接口。 但是,我在编写将这些类型分组为集群的代码时遇到了很多麻烦,而且我不理解标题中提到的错误。 我给出这个上下文以防我遇到一个明显的 XY 问题,但这似乎是迄今为止我发现的最有希望的路径。
到目前为止,这是代码的简化版本,我注释掉了某些包含,以便您可以将其复制粘贴为一个块进行测试,但将它们保留为注释,以便您了解在真实示例中应该如何链接。 为简洁起见,我还排除了 header 防护装置,但假设标题将具有标准 header 防护装置:
// AStruct.hpp
// special group of 'A' structs (assume these are complex types and we can't control their inheritance chain)
struct A0{};
struct A1{};
struct A2{};
struct A3{};
struct A4{};
struct A5{};
struct A6{};
struct A7{};
struct A8{};
struct A9{};
// BStruct.hpp
// special group of 'B' structs (assume these are complex types and we can't control their inheritance chain)
struct B0{};
struct B1{};
struct B2{};
struct B3{};
struct B4{};
struct B5{};
struct B6{};
struct B7{};
struct B8{};
struct B9{};
// TypeList.hpp
#include <type_traits>
template<typename ... Types>
struct TypeList;
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf;
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head> struct OneOf<Evaluator, Term, TypeList<Head> >
{
using value = std::bool_constant<Evaluator<Term, Head>::value>;
};
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf<Evaluator, Term, TypeList<Head, Tail...> >
{
using value = std::bool_constant<Evaluator<Term, Head>::value || OneOf<Evaluator, Term, TypeList<Tail...> >::value>;
};
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail >
inline constexpr bool OneOfV = OneOf<Evaluator, Term, TypeList<Head, Tail...> >::value;
// AStructUtils.hpp
// #include TypeList.hpp
// #include AStruct.hpp
// This is setup as a macro so that other macros can consume it in addition
// to templates with TypeList
#define A_STRUCT_TYPES \
A0, \
A1, \
A2, \
A3, \
A4, \
A5, \
A6, \
A7, \
A8, \
A9
template<typename AStruct>
using AStructTypes = TypeList <A_STRUCT_TYPES>;
template< typename AStruct >
inline constexpr bool IsAStructV = OneOfV<std::is_same, AStruct, AStructTypes >::value;
// BStructUtils.hpp
// #include TypeList.hpp
// #include BStruct.hpp
// This is setup as a macro so that other macros can consume it in addition
// to templates with TypeList
#define B_STRUCT_TYPES \
B0, \
B1, \
B2, \
B3, \
B4, \
B5, \
B6, \
B7, \
B8, \
B9
template<typename BStruct>
using BStructTypes = TypeList <B_STRUCT_TYPES>;
template< typename BStruct >
inline constexpr bool IsBStructV = OneOfV<std::is_same, BStruct, BStructTypes >::value;
// Driver main.cpp includes
// #include AStructUtils.hpp
// #include BStructUtils.hpp
#include <string>
#include <iostream>
int main()
{
std::string buffer;
buffer.append( "A4 is a AStruct type: " + std::to_string( IsAStructV<A4> ) + "\n" ); // 1
buffer.append( "B4 is a AStruct type: " + std::to_string( IsAStructV<B4> ) + "\n" ); // 0
buffer.append( "A4 is a BStruct type: " + std::to_string( IsBStructV<A4> ) + "\n" ); // 0
buffer.append( "B4 is a BStruct type: " + std::to_string( IsBStructV<B4> ) + "\n" ); // 1
std::cout << buffer << std::flush;
}
这是完整的错误:
:68:36: 错误:变量模板 id 'OneOfV struct std::is_same, AStruct, template using AStructTypes = TypeList >' in nested-name-specifier
这是 GodBolt 中的示例: https://godbolt.org/z/Mber5YToY
将类型别名为value
有点不寻常。 相反,我建议您将其声明为 static 成员,以便您可以使用变量模板直接提取它。
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf;
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head> struct OneOf<Evaluator, Term, TypeList<Head> >
{
static inline constexpr bool value = std::bool_constant<Evaluator<Term, Head>::value>::value;
};
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf<Evaluator, Term, TypeList<Head, Tail...> >
{
static inline constexpr bool value = Evaluator<Term, Head>::value || OneOf<Evaluator, Term, TypeList<Tail...> >::value;
};
在您的情况下,变量模板OneOfV
的模板参数应该与Oneof
完全相同。
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail >
inline constexpr bool OneOfV = OneOf<Evaluator, Term, Head, Tail...>::value;
否则, IsAStructV<A4>
将扩展为OneOf<std::same_as, A4, TypeList<AStructTypes>>::value
,其中第三个参数应为AStructTypes
。
此外, AStructTypes
没有理由成为模板。 这是一个确定的类型。 BStructTypes
也是如此。
using AStructTypes = TypeList <A_STRUCT_TYPES>;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.