【问题标题】:c++ template for constant data holder class常量数据持有者类的c ++模板
【发布时间】:2017-01-08 09:56:06
【问题描述】:

我正在尝试设计一个其所有数据都是常量并且在编译时知道的类。我可以通过手动输入来创建它,但我想使用一个模板,这样我就不必多次重写几乎相同的代码。

我在想模板是这样做的方法,例如

template<class T> class A { ... }

A<float>
A<MyObject>
A<int>

但后来我不确定如何将我知道的常量数据获取到这个对象中。我可以在运行时使用一个成员函数来执行此操作,该函数对类型或类似的东西执行 switch 语句,但我理想地希望它有效地成为我使用的哑数据持有者。

所以在A&lt;float&gt; 的情况下,我会这样:

// member function
int getSize() {
    return 4;
}

代替(伪代码)

// member function
int getSize() {
    if (type == float) {
        return 4;
    } else if ...
}

我想知道是否有已知的方法可以做到这一点?我对 constexpr 没有任何经验,这可能是关键吗?

编辑:澄清:我希望成员函数始终根据模板化类型/类返回相同的结果。例如,A 总是从 getSize() 返回 4,从 getSomethingElse() 返回 1,从 getAnotherThing() 返回 6.2。其中 A 将从 getSize() 返回 8,从 getSomethingElse() 返回 2,从 getAnotherThing() 返回 8.4。

【问题讨论】:

  • 你试过std::type_info吗?
  • 你在重新实现sizeof吗?
  • 这个模板应该做什么const double x = 0.75;没有?
  • @LogicStuff 不,我看到 getSize 现在是一个不好的例子,但该对象还有其他方法只对我有意义。
  • @LYF_HKN 类型特征,但我自己的特征。

标签: c++ templates c++14 constexpr


【解决方案1】:

你可以拥有这个模板

template <int size_, int foo_, int bar_>
struct MyConstData {
   static const int size = size_; // etc
};

然后专门化你的模板:

template <class T> class A;
template <> class A<float> : MyConstData<13,42,-1> {};
template <> class A<double> : MyConstData<0,0,42> {};

【讨论】:

  • 但是,如果您想要为您的专用模板的所有其他成员函数在 A 类的原始定义中声明的模板化实现怎么办?
  • 如果 OP 真的只是在做类型特征样式类,我最喜欢这个。
  • @Omnifarious 据我了解,OP 是在询问如何定义 A,而不是如何处理已定义的 A。如果您想要在非专业 A 中使用默认实现,只需为其提供定义.
  • 我会玩这个,但我认为这正是我需要的,我会尽快通知你。
【解决方案2】:

您可以专门化一个类中的特定功能,并且根据您对事物的描述,我怀疑这就是您想要的。以下是其工作原理的示例:

#include <iostream>
#include <string>

template <class T>
class A {
 public:
   int MyConstantFunction() const { // Default implementation
      return 0;
   }
};

template <>
int A<int>::MyConstantFunction() const
{
   return 3;
}

template <>
int A<float>::MyConstantFunction() const
{
   return 5; // If you examine the world, you'll find that 5's are everywhere.
}

template <>
int A<double>::MyConstantFunction() const
{
   return -5;
}

int main(int, char *[])
{
   using ::std::cout;
   A<int> aint;
   A<float> afloat;
   A<long> along;

   cout << "aint.MyConstantFunction() == " << aint.MyConstantFunction() << '\n';
   cout << "afloat.MyConstantFunction() == "
        << afloat.MyConstantFunction() << '\n';
   cout << "along.MyConstantFunction() == "
        << along.MyConstantFunction() << '\n';
   return 0;
}

注意along 是如何使用类声明中的默认实现的。这凸显了这里的危险。如果为给定类型使用您的专业化的翻译单元没有看到该专业化,它将不会使用它,这可能会导致各种有趣的问题。确保发生这种情况。

另一种选择是根本不提供默认实现,因此会出现实例化错误。

我的直觉是,您正在做一些毫无意义且设计不佳的事情。但是,由于我不知道完整的上下文,我不能肯定地说。如果您坚持这样做,请按照以下方法操作。

【讨论】:

    【解决方案3】:

    如果你想根据类型实现不同的东西,你可以试试这个:

    template <class T>
    class Foo {
        T data;
    
        string toString() {
             return myGeneralToString(data);
        }
    };
    
    template <>
    class Foo<string> {
        string data;
    
        string toString() {
            return "Already a string: " + data;
        }
    };
    

    如果你只想要模板化的常量,我会试试这个:

    template <int a, int b>
    class Calc {
    public:
        static constexpr int SUM = a + b;
    };
    
    int main()
    {
        std::cout << Calc<3, 5>::SUM << std::endl;
    
        return 0;
    }
    

    编辑:正如 Omnifarious C++14 所指出的,有模板化的常量,而没有模板化类本身。因此,您可以将示例简化为:

    class Calc {
    public:
        template <int a, int b>
        static constexpr int SUM = a + b;
    };
    
    int main()
    {
        std::cout << Calc::SUM<3, 5> << std::endl;
    
        return 0;
    }
    

    【讨论】:

    • @TomShar 这对你有帮助还是我误解了这个问题?
    • C++14 有实际的模板化常量。你会用惯用的 C++14 写 template &lt;int a, int b&gt; constexpr int CalcSum = a + b;
    • @Omnifarious 啊我不知道。我会把它添加到答案中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2013-07-11
    • 1970-01-01
    • 2015-03-06
    相关资源
    最近更新 更多