C++17:编译时将类型映射为整数值

C++17:编译时将类型映射为整数值,c++,templates,c++17,template-meta-programming,C++,Templates,C++17,Template Meta Programming,我有以下几种: 结构A{}; 结构B{}; 结构C{}; 样板 结构定义{ 使用消息类型=类; 静态constexpr uint16_t tag=i; }; 这个元组: constexpr auto types=std::make_tupledef,def,def; 类型A、B和C应映射到相应的值A->1等。。我想创建一些函数,结构,这些类型的给定对象将返回正确的值。我试着做了以下几点: 样板 结构gettag{ 静

我有以下几种:

结构A{}; 结构B{}; 结构C{}; 样板 结构定义{ 使用消息类型=类; 静态constexpr uint16_t tag=i; }; 这个元组:

constexpr auto types=std::make_tupledef,def,def; 类型A、B和C应映射到相应的值A->1等。。我想创建一些函数,结构,这些类型的给定对象将返回正确的值。我试着做了以下几点:

样板 结构gettag{ 静态decltypeT::tagvaluetypename T::message_type const&{return T::tag;} }; 样板 结构tagdb:public gettag。。。{ tagdbstd::tuple const&t{} }; int main{ tagdb类型; A A;
std::cout问题在于您有模板基类,所有这些基类都声明了一个具有相同名称的成员。最简单的修复方法就是将所有基类值函数拉入派生类:


使用gettag,我建议不使用std::tuple和gettag的解决方案:


很好的解决方案,谢谢,不幸的是这个元组是必须的,它是由protobuf编译器插件生成的,我不能更改它。除此之外,你的解决方案很好,我将看看将来它是否可以用于我们的解决方案。谢谢。@JędrzejDudkiewicz你可以使用注释重载从std::tuple构造tagdb。实际上,在我键入我的答案后,我意识到我基本上重复了Anthony的答案,只是稍微简化了一下,删除了看起来多余的gettag类。谢谢,这确实很有魅力。虽然模板基类声明了相同的名称,但它们使用不同的参数类型。那么哪条规则说它们不能不使用?我支持它是基本的。它是名称查找:依赖于外部类模板的模板参数的类模板的成员模板基类不考虑用于查找非依赖名称。使用使它们成为tagdb类的成员,因此在名称查找过程中会考虑它们。好的,这不是那么基本,谢谢。难怪我我不知道发生了什么。这看起来太复杂了,尽管我认为不这样做有时会让事情变得非常神秘。
x.cc: In function ‘int main()’:
x.cc:29:17: error: request for member ‘value’ is ambiguous
   29 |  std::cout << t.value(a) << '\n';
      |                 ^~~~~
x.cc:16:26: note: candidates are: ‘static decltype (T::tag) gettag<T>::value(const typename T::message_type&) [with T = def<C, 3>; decltype (T::tag) = const short unsigned int; typename T::message_type = C]’
   16 |  static decltype(T::tag) value(typename T::message_type const&) { return T::tag; }
      |                          ^~~~~
x.cc:16:26: note:                 ‘static decltype (T::tag) gettag<T>::value(const typename T::message_type&) [with T = def<B, 2>; decltype (T::tag) = const short unsigned int; typename T::message_type = B]’
x.cc:16:26: note:                 ‘static decltype (T::tag) gettag<T>::value(const typename T::message_type&) [with T = def<A, 1>; decltype (T::tag) = const short unsigned int; typename T::message_type = A]’
struct A { }; 
struct B { }; 
struct C { }; 

template <typename Class, std::uint16_t i>     
struct def {                              
    static constexpr std::uint16_t value(Class) {
        return i;
    }
};  

template <typename... Tags>                                                              
struct tagdb : public Tags... {                                                  
    using Tags::value...;
};

template<class... Tags>
constexpr auto make_tagdb(Tags...) {
    return tagdb<Tags...>{};
}

// template<class... Tags>
// constexpr auto make_tagdb(std::tuple<Tags...>) {
//     return tagdb<Tags...>{};
// }

constexpr auto tags = make_tagdb(def<A, 1>(), def<B, 2>(), def<C, 3>());

int main() {                            
    A a;                            
    std::cout << tags.value(a) << '\n';   // Output: 1
}