C++ 从类/结构中声明的枚举类型到也在该类/结构中声明的对等静态方法?
简单地说:在一个以枚举类型为参数的模板中(不是作用域枚举,一个常规的旧C++11之前的枚举),我需要调用一个方法,该方法在与枚举相同的结构中声明,它以枚举值为参数。有办法做到这一点吗 全文:假设我是“自作用域”非作用域枚举,如下所示:C++ 从类/结构中声明的枚举类型到也在该类/结构中声明的对等静态方法?,c++,enums,C++,Enums,简单地说:在一个以枚举类型为参数的模板中(不是作用域枚举,一个常规的旧C++11之前的枚举),我需要调用一个方法,该方法在与枚举相同的结构中声明,它以枚举值为参数。有办法做到这一点吗 全文:假设我是“自作用域”非作用域枚举,如下所示: struct W{ 枚举E{A,B,C}; 静态字符串foo(枚举E); }; 现在假设我有一堆遵循此模式的结构声明-每个声明都有一个enum,尽管enum类型的名称不同,并且每个声明都有一个静态方法foo,使用一个属于该enum类型的参数 现在,我想创建一个模
struct W{
枚举E{A,B,C};
静态字符串foo(枚举E);
};
现在假设我有一堆遵循此模式的结构声明-每个声明都有一个enum,尽管enum类型的名称不同,并且每个声明都有一个静态方法foo
,使用一个属于该enum类型的参数
现在,我想创建一个模板,给定一组枚举类型,这些枚举类型希望根据各自的foo()
模板
向量变换(常量向量es){
矢量ss;
对于(E:es){
ss.推回(foo(e));
}
返回ss;
}
现在我实例化xform
:
。。。
向量为{W::A,W::C};
自动Wx=变换(as);
...
当然,我得到了一个编译器错误,因为编译器找不到正确的foo
来调用:
prog.cc: In instantiation of 'std::vector<std::__cxx11::basic_string<char> > xform(std::vector<E>) [with E = W::A]':
prog.cc:34:24: required from here
prog.cc:24:21: error: 'foo' was not declared in this scope
24 | ss.push_back(foo(e));
| ~~~^~~
prog.cc:std::vector xform(std::vector)[with E=W::A]的实例化中:
进度cc:34:24:从这里开始需要
prog.cc:24:21:错误:“foo”未在此作用域中声明
24 | ss.推回(foo(e));
| ~~~^~~
(仅此而已。)
所以我需要从枚举类型到它的对等方法。我可以这样做吗-怎么做?(因为对等方法的名称总是相同的,所以这一部分很简单——我不知道如何从枚举类型转换到它的封闭类型。)
(显然,如果每个结构中的枚举类型的名称相同,我可以通过使用结构的名称作为模板参数来解决这个问题。但是在我的用例中,枚举都有不同的名称。)
分辨率(此时):虽然在这种特殊情况下非常简单不起作用,因为函数foo
不依赖于模板函数xform
中的类型参数,因此,与查找和ADL相关的规则以及模板中的非依赖名称意味着,如果您试图在其他命名空间的代码中隐式实例化xform
,则不能使用ADL。(我不确定我是否理解为什么,但这是事实。)错误是在模板实例化时找不到名称,只有在声明时(并且只有通过ADL)。我想你可以通过显式实例化来解决这个问题。。。但是
使用traits的方法非常有效,也不单调,而且完全可以在不修改现有包装枚举的情况下完成。简单地说,不,你不能这样做。原因有二,
vector
和template vector xform(const vector es)
不允许您找到包含函数foo()
的结构。这是因为std::vector::_Ty=enum W::A
基本上是enum
类型。如何从enum
类型中找到struct
在结构或类中定义静态foo()
函数时,该函数位于结构/类的作用域中(与命名空间W{string foo(…){…}
)。这就是此错误的原因:prog.cc:24:21:错误:未在此范围内声明“foo”
如何解决此问题?
我想到的唯一合理的选择是将foo()
函数放在全局范围内,并为其提供覆盖。它看起来像这样
struct W1{
枚举A{A,B,C};
};
字符串foo(enumw1::aaa){returnstd::array{“A”、“B”、“C”}[A];}
结构W2{
枚举B{X,Y,Z,};
};
字符串foo(enumw2::bb){returnstd::array{“X”、“Y”、“Z”}[B];}
现在,xform()
函数可以解决编译时要使用的foo()
,而不存在任何范围问题。简单地说,不,你不能这样做。原因有二,
vector
和template vector xform(const vector es)
不允许您找到包含函数foo()
的结构。这是因为std::vector::_Ty=enum W::A
基本上是enum
类型。如何从enum
类型中找到struct
在结构或类中定义静态foo()
函数时,该函数位于结构/类的作用域中(与命名空间W{string foo(…){…}
)。这就是此错误的原因:prog.cc:24:21:错误:未在此范围内声明“foo”
如何解决此问题?
我想到的唯一合理的选择是将foo()
函数放在全局范围内,并为其提供覆盖。它看起来像这样
struct W1{
枚举A{A,B,C};
};
字符串foo(enumw1::aaa){returnstd::array{“A”、“B”、“C”}[A];}
结构W2{
枚举B{X,Y,Z,};
};
字符串foo(enumw2::bb){returnstd::array{“X”、“Y”、“Z”}[B];}
现在,xform()
函数可以解决编译时要使用的foo()
,而不存在任何范围问题。我不知道这是否有可能,我也不认为有可能
一个相对便宜的替代方法是手工维持名字之间的联系。在下面的示例代码中,这是通过辅助模板的专门化来完成的
#包括
#包括
使用std::string;
使用std::vector;
结构W1{
枚举E1{A,B,C};
静态字符串foo(枚举e1e);
};
结构W2{
枚举E2{A,B,C};
静态字符串foo(枚举e2e);
};
模板结构WX;
模板结构WX{u
#include <string>
#include <vector>
using std::string;
using std::vector;
struct W1 {
enum E1 { A, B, C };
static string foo(enum E1 e);
};
struct W2 {
enum E2 { A, B, C };
static string foo(enum E2 e);
};
template<typename T> struct WX;
template<> struct WX<W1::E1> { using W = W1; };
template<> struct WX<W2::E2> { using W = W2; };
template<typename E> vector<string> xform(const vector<E> es) {
vector<string> ss;
for (E e : es) {
ss.push_back(WX<E>::W::foo(e));
}
return ss;
}
void bar()
{
vector<enum W1::E1> a1s { W1::A, W1::C };
auto w1x = xform(a1s);
vector<enum W2::E2> a2s { W2::A, W2::C };
auto w2x = xform(a2s);
}