简体   繁体   English

从类/结构中声明的枚举类型获取也在该类/结构中声明的对等 static 方法?

[英]From enum type declared in a class/struct get to a peer static method also declared in that class/struct?

Briefly: In a template that takes an enum type as parameter ( not a scoped enum, a regular old pre-C++11 enum) I need to call a method, declared in the same struct as the enum, which takes an enum value as its parameter.简而言之:在一个以枚举类型作为参数的模板中(不是作用域枚举,一个常规的旧 C++11 之前的枚举)我需要调用一个方法,在与枚举相同的结构中声明,它接受一个枚举值作为它的参数。 Is there a way to do this?有没有办法做到这一点?

In full: Suppose I'm "self-scoping" unscoped enums as follows:完整:假设我是“自我范围界定”无范围枚举,如下所示:

struct W {
   enum E { A, B, C };

   static string foo(enum E e);
};

Now suppose I have a bunch of these struct declarations following this pattern - each has an enum though the enum type's name is different and each has a static method foo taking one argument which is of that enum type.现在假设我有一堆遵循这种模式的结构声明——每个都有一个枚举,尽管枚举类型的名称不同,每个都有一个 static 方法foo接受一个属于该枚举类型的参数。

Now I want to create a template that given a bunch of one of these enum types wants to transform each one according to its own foo() :现在我想创建一个模板,给定一堆这些枚举类型中的一种,想要根据自己的foo()转换每个类型:

template <typename E>
vector<string> xform(const vector<E> es) {
  vector<string> ss;
  for (E e : es) {
    ss.push_back(foo(e));
  }
  return ss;
}

Now I instantiate xform :现在我实例化xform

...
    vector<enum W::A> as{W::A, W::C};
    auto Wx = xform(as);
...

and of course I get a compiler error because the compiler can't find the right foo to call:当然我得到一个编译器错误,因为编译器找不到正确的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));
      |                  ~~~^~~

(This is all here on wandbox .) (这一切都在 wandbox 上。)

So I need to get from the enum type to its peer method.所以我需要从枚举类型到它的对等方法。 Can I do that - how?我可以那样做吗?怎么做? (Since the peer method's name is always the same that part's easy - I don't know how to get from the enum type to its enclosing type.) (由于对等方法的名称始终相同,所以这部分很简单——我不知道如何从枚举类型获取其封闭类型。)

(Obviously I can solve this if the enum type's name in each struct is the same, by using the struct's name as the template argument. But in my use case the enums all have different names.) (显然,如果每个结构中的枚举类型的名称相同,我可以通过使用结构的名称作为模板参数来解决这个问题。但在我的用例中,枚举都有不同的名称。)

Resolution (at this point) : D-RAJ's answer though very simple doesn't work in this particular case because of the function foo is not dependent on the type parameter in the template function xform , thus the rules related to lookup and ADL and a non-dependent name in a template mean that ADL can not be used if you try to implicitly instantiate xform in code in some other namespace.解决方案(此时)D-RAJ 的回答虽然非常简单,但在这种特殊情况下不起作用,因为 function foo依赖于模板 function xform中的类型参数,因此与查找和 ADL 相关的规则和模板中的非依赖名称意味着如果您尝试在某些其他命名空间的代码中隐式实例化xform ,则无法使用 ADL。 (I'm not sure I understand why, but that's the fact.) The error is that the name cannot be found at the point of template instantiation, only at the point of declaration (and only then via ADL). (我不确定我理解为什么,但事实就是如此。)错误是在模板实例化时找不到名称,只能在声明时找到(然后才通过 ADL)。 I guess you could get around that with explicit instantiations... but...我想你可以通过显式实例化来解决这个问题......但是......

dxiv's answer of using traits works great, is not onorous, and it can be done without modifying the existing wrapped-enums at all. dxiv 关于使用 traits 的回答效果很好,并不繁琐,而且根本不需要修改现有的 wrapped-enums 就可以完成。

In simple, No, you cant do it like that.简而言之,不,你不能那样做。 There are 2 reasons for this,这有两个原因,

  1. vector<enum W::A> and template <typename E> vector<string> xform(const vector<E> es) doesn't let you find which struct contains the function foo() . vector<enum W::A>template <typename E> vector<string> xform(const vector<E> es)不会让您找到哪个结构包含 function foo() This is because the std::vector::_Ty = enum W::A which is basically an enum type.这是因为std::vector::_Ty = enum W::A基本上是一个enum类型。 How can you find a struct from an enum type?如何从enum类型中找到struct
  2. When you define the static foo() function in a struct or class, the function is in the scope of the struct/ class (its the same as namespace W { string foo(...) {... } } ).当您在结构或 class 中定义 static foo() function 时,function 在结构的 scope/class 中(它与namespace W { string foo(...) {... } } This is the reason for this error: prog.cc:24:21: error: 'foo' was not declared in this scope .这就是此错误的原因: prog.cc:24:21: error: 'foo' was not declared in this scope

How to resolve this issue?如何解决这个问题?
The only reasonable option that comes to my mind is to put the foo() function in the global scope and provide overrides to it.我想到的唯一合理的选择是将foo() function 放在全局 scope 中并为其提供覆盖。 It would look something like this.它看起来像这样。

struct W1 {
    enum A { A, B, C };
};

string foo(enum W1::A a) { return std::array{ "A","B","C" } [a] ; }

struct W2 {
    enum B { X, Y, Z, };
};

string foo(enum W2::B b) { return std::array{ "X", "Y", "Z" } [b] ; }

Now the xform() function can resolve which foo() to be used at compile time without any scope issues.现在xform() function 可以解决在编译时使用哪个foo()而没有任何 scope 问题。

I don't know that it's possible as stated, and don't think it is.我不知道这是否可能如前所述,也不认为是。

A relatively cheap alternative could be to maintain the association between names by hand.一种相对便宜的替代方法可能是手动维护名称之间的关联。 In the sample code below, this is done by specializations of a helper template WX<> (tried here ).在下面的示例代码中,这是通过辅助模板WX<>的特化来完成的(在此处尝试)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM