【问题标题】:C++: Redefinition of template class with different typesC++:用不同类型重新定义模板类
【发布时间】:2017-03-18 18:55:37
【问题描述】:

我有两个(多个)枚举:

enum Choices1 : int
{
    a,
    b
};
enum Choices2 : int
{
    c,
    d
};

我希望能够将类型与这些枚举选项中的每一个相关联。如果我只有一组枚举说Choices1,我可以介绍:

template <Choices1 c>
struct choice_traits; 

然后为每个条目专门化它:

template <>
struct choice_traits<Choices1::a> 
{
    using MyType = float;
};

template <>
struct choice_traits<Choices1::b> 
{
    using MyType = double;

但我希望能够为多个枚举做到这一点,同时使用相同的关键字,即:

template <>
struct choice_traits<Choices1::a>
{...};

template <>
struct choice_traits<Choices1::b>
{...};

template <>
struct choice_traits<Choices2::c>
{...};

template <>
struct choice_traits<Choices2::d>
{...};

这可能吗?如果是这样,非特化的情况是什么?

如果没有,是否有任何替代方法可以将类型关联到每个 (Choice1::a,Choice1::b,Choice2::c,Choice2::d) 以及可能更多这样的枚举?

【问题讨论】:

  • 我认为 c++1z 自动模板参数可以在这里解决问题。 Example
  • 有趣!在那之前还有什么?
  • 恐怕在 c++1z 之前你需要将枚举的类型与值一起传递...
  • 是的,我正在努力避免这种情况。 ://
  • 是的,我从您的问题中得知...我不喜欢宏,但也许 this 可能是您的答案

标签: c++ c++11 templates enums template-specialization


【解决方案1】:

不是一个很好的解决方案,但是...您可以使用 Choiches1Choiches2 的公共基础 (int),并将非特殊情况定义为

template <int>
struct choice_traits;

此时的问题是 Choiches1::a == Coiches2::cChoiches1::b == Choiches2::d 所以,如果你想定义类似的东西

template <>
struct choice_traits<Choices1::a> 
 { using MyType = float; };

template <>
struct choice_traits<Choices1::b> 
 { using MyType = double; };

template <>
struct choice_traits<Choices2::c> 
 { using MyType = int; };

template <>
struct choice_traits<Choices2::d> 
 { using MyType = long; };

你必须避免Choiches1Choiches2 值之间的冲突。

如果你知道Choiches1值的个数,你可以用更大的数字开始Choiches2;例如,如果您确定有小于 100 个 Choiches1 值,则可以按如下方式定义枚举

enum Choices1 : int
{ a = 0, b };

enum Choices2 : int
{ c = 100, d };

另一种解决方案是对两个枚举使用偶数和奇数值;像

enum Choices1 : int
{ a = 0, b = a+2 }; // add 2 for every next value

enum Choices2 : int
{ c = 1, d = c+2 }; // add 2 for every next value

以下是一个完整的例子

enum Choices1 : int
{ a = 0, b };

enum Choices2 : int
{ c = 100, d };

template <int>
struct choice_traits;

template <>
struct choice_traits<Choices1::a> 
 { using MyType = float; };

template <>
struct choice_traits<Choices1::b> 
 { using MyType = double; };

template <>
struct choice_traits<Choices2::c> 
 { using MyType = int; };

template <>
struct choice_traits<Choices2::d> 
 { using MyType = long; };

int main()
 {
   choice_traits<a>::MyType fl { 1.1f };
   choice_traits<b>::MyType db { 2.2 };
   choice_traits<c>::MyType in { 3 };
   choice_traits<d>::MyType ln { 4L };
 } 

【讨论】:

  • 不错的黑客。不幸的是,这意味着这些枚举的提供者必须负责管理他们的值,以便使用我在上面构建的choice_traits 框架,我认为这个要求太多了。
【解决方案2】:

这里有一些过度的解决方案:

template <class Enum, Enum e>
struct choice_traits;

template<>
struct choice_traits<Choices1, Choices1::b>
{
      typedef float MyType;
};

//using
typename choice_traits<Choices1, Choices1::b>::MyType m {0.0};

【讨论】:

    猜你喜欢
    • 2019-06-09
    • 2015-07-28
    • 2011-02-17
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多