C++ 从类/结构中声明的枚举类型到也在该类/结构中声明的对等静态方法?

C++ 从类/结构中声明的枚举类型到也在该类/结构中声明的对等静态方法?,c++,enums,C++,Enums,简单地说:在一个以枚举类型为参数的模板中(不是作用域枚举,一个常规的旧C++11之前的枚举),我需要调用一个方法,该方法在与枚举相同的结构中声明,它以枚举值为参数。有办法做到这一点吗 全文:假设我是“自作用域”非作用域枚举,如下所示: struct W{ 枚举E{A,B,C}; 静态字符串foo(枚举E); }; 现在假设我有一堆遵循此模式的结构声明-每个声明都有一个enum,尽管enum类型的名称不同,并且每个声明都有一个静态方法foo,使用一个属于该enum类型的参数 现在,我想创建一个模

简单地说:在一个以枚举类型为参数的模板中(不是作用域枚举,一个常规的旧C++11之前的枚举),我需要调用一个方法,该方法在与枚举相同的结构中声明,它以枚举值为参数。有办法做到这一点吗

全文:假设我是“自作用域”非作用域枚举,如下所示:

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);
    }