类中同名嵌套类型与成员函数导致std::is_same_v编译错误
类中嵌套结构体与成员函数同名的编译错误解决(无需修改原类)
编译错误:
error C2923: 'std::is_same_v': 'A::B' is not a valid template type argument for parameter '<unnamed-symbol>'
这并非《C++中函数与结构体同名》的重复案例。当类A中同时存在嵌套结构体B和同名成员函数B()时,直接在模板中使用A::B会被编译器优先解析为成员函数,导致无法作为模板类型参数传递给std::is_same_v,触发上述编译错误。
将A类中的成员函数B()重命名为BB()并同步修改调用处,代码可正常编译,但实际场景中(如GRPC自动生成的Stub类,同时包含async嵌套类与async()成员函数)无法修改原类结构,因此需要无需修改struct A的编译通过方案。
原错误代码如下:
#include <iostream> // 主模板 template<typename T> struct ClassOf { }; // 偏特化 template<typename Return, typename Class> struct ClassOf<Return(Class::*)> { using type = Class; }; // 类型别名 template<typename T> using ClassOf_t = typename ClassOf<T>::type; struct A { struct B { void methodB () {} }; B* myPtr; // 重命名为BB()并同步修改L29调用即可编译 B* B() { return myPtr; } // <- 第22行 }; struct C { template <typename T> T* getClient() { if constexpr (std::is_same_v<A::B,T>) { return myA.B(); // <- 第29行 } } A myA; }; int main() { auto fn = &A::B::methodB; ClassOf_t<decltype(fn)> a; a.methodB(); C c; auto res = c.getClient<ClassOf_t<decltype(fn)>>(); res->methodB(); return 0; }
可行解决方案
1. 用typename强制指定为类型
在std::is_same_v中,通过typename A::B明确告知编译器这是一个嵌套类型,而非成员函数:
struct C { template <typename T> T* getClient() { if constexpr (std::is_same_v<typename A::B,T>) { return myA.B(); } } A myA; };
原理:当类中存在同名的类型与成员时,直接写A::B会优先解析为成员函数,加上typename后,编译器会优先查找嵌套类型。
2. 通过成员变量推导类型
利用A类中已有的myPtr成员的类型间接获取A::B,避免直接写A::B的歧义:
#include <type_traits> // 需要引入头文件 struct C { template <typename T> T* getClient() { using A_B_Type = std::remove_pointer_t<decltype(std::declval<A>().myPtr)>; if constexpr (std::is_same_v<A_B_Type,T>) { return myA.B(); } } A myA; };
原理:std::declval<A>().myPtr生成myPtr的表达式,decltype得到其类型为A::B*,再通过std::remove_pointer_t去掉指针,最终得到A::B类型。
3. 复用已有的ClassOf_t类型别名
借助main函数中已有的逻辑,通过成员函数指针提取A::B类型,提前定义别名后使用:
// 全局或C类内部定义类型别名 using A_B_Type = ClassOf_t<decltype(&A::B::methodB)>; struct C { template <typename T> T* getClient() { if constexpr (std::is_same_v<A_B_Type,T>) { return myA.B(); } } A myA; };
原理:通过成员函数指针&A::B::methodB,利用已有的ClassOf模板提取出所属的类A::B,绕开直接写A::B的歧义。
内容的提问来源于stack exchange,提问作者Nele
相关产品推荐
相关产品推荐

