【问题标题】:C++ template specialization to provide/add different member functions提供/添加不同成员函数的 C++ 模板特化
【发布时间】:2012-11-20 14:50:48
【问题描述】:

我正在尝试一些类型特征和模板专业化。例如:

enum TestEnum
{
    VALUE0 = 0,
    VALUE1 = 1,
    VALUE2 = 2
    //... And so on...
};

template<int Value>
class cTestClass;

//specializations
template<>
class cTestClass<VALUE0>
{
    static int GetVal() { return VALUE0; }
};

template<>
class cTestClass<VALUE1>
{
    static int GetVal() { return VALUE1; }
};

template<>
class cTestClass<VALUE2>
{
    static int GetVal() { return VALUE2; }
};

typedef cTestClass<VALUE0> cClassVal0; //(1)
typedef cTestClass<VALUE1> cClassVal1; //(2)
typedef cTestClass<VALUE2> cClassVal2; //(3)

//Later in the code
template<int Value>
cTestClass<Value>* Create()
{
    return new cTestClass<Value>(/*..*/);
}

//And using the upper function
cClassVal2* pTestClass = Create<VALUE2>();

这绝对没问题。目标是为界面用户提供一种不处理模板和模板参数的方法(好的,除了使用 Create())。这就是代码底部的 typedef 的原因。

不,这是我接下来要实现的目标: cTestClass 应该有一个可以通过成员函数访问的成员变量。在某些情况下,我希望用户能够修改成员变量或不修改成员变量。所以基本上这意味着两个成员函数,一个将成员作为 const 引用(不可修改)或非 const(可修改)返回。问题是,如果提供了这两个成员函数,用户总是有机会修改成员变量。所以我想在编译时选择合适的成员函数,只为用户提供一个正确的成员函数。

我想出的唯一解决方案基本上是这样的:

template<int Value, bool ConstAccess>
class cTestClass;

//specializations
template<>
class cTestClass<VALUE0, true>
{
    const std::string& get() const
    {
        return m_strName;
    }

    static int GetVal() { return VALUE0; }

private:
    std::string m_strName;
};

template<>
class cTestClass<VALUE0, false>
{
    std::string& get()
    {
        return m_strName;
    }

    static int GetVal() { return VALUE0; }

private:
    std::string m_strName;
};

//For every upcoming cTestClass two specializations

typedef cTestClass<VALUE0, true> cConstObjectVal0;
typedef cTestClass<VALUE0, false> cObjectVal0;
//And for the rest...

除了这确实是不必要的代码重复之外,我总是必须为每个可能的 VALUE 指定两个 typedef。但是用户不应该面临这样的选择,他应该总是能够只使用上面给出的类型(参见 1、2、3)。

这可能吗?

我用谷歌搜索了一下,找到了以下网站:ACCU:: An introduction to C++ traits。 这个解释似乎是一个匹配的蓝图,但我真的无法将各个部分放在一起。 我发现的另一种可能性在这里描述:C++ Template specialization to provide extra member function? 只添加一个函数是可能的,但这仍然不能解决我的 typedef 问题。

【问题讨论】:

  • 为什么有人不能直接使用const cObjectVal0?这消除了使用非常量成员函数的能力。
  • 我不确定你在问什么。您的代码的第二个版本是否有效?如果它不起作用,那是因为您忘记在 cTestClass 声明中添加第二个模板参数,它应该是template&lt;int Value, bool&gt; class cTestClass
  • 如果您不想让用户选择是否获得 const,您可以 typedef 只选择适当的专业化,不是吗?像typedef cTestClass&lt;VALUE0, true&gt; cClassVal0; typedef cTestClass&lt;VLAUE1, false&gt; cClassVal1; 等等。
  • @BeyondSora:第二个版本正在运行,缺少的声明是一个错字。修好了。
  • @VaughnCato:不太清楚你的意思。如果我们使用 Create() 函数并将返回值设为cTestClass&lt;Value&gt; const * Create(),这将起作用,对吧。但是我们改变这个函数不返回一个指针怎么样,比如cTestClass&lt;Value&gt; Create()。也许我应该在示例中更清楚地说明这一点。

标签: c++ templates typedef template-specialization typetraits


【解决方案1】:

我们可以试试SFINAE:

typedef char True;
typedef long False;

template <typename VALUE0, typename IsConst>
class cTestClass
{
public:

    template <typename T, T> struct TypeCheck {};

    const std::string& get(TypeCheck<IsConst, True >* dummy = NULL);
          std::string& get(TypeCheck<IsConst, False>* dummy = NULL);
}

typedef cTestClass<VALUE0, True>  cConstObjectVal0;
typedef cTestClass<VALUE0, False> cObjectVal0;

我还没有尝试编译它,但总的原则是阻止其中一个函数正确编译,然后,由于SFINAE 的原则,编译器只会丢弃错误的版本。

【讨论】:

  • 谢谢你,我会进一步关注这个。但是我们仍然有两个 typedef,最终目标是只为用户提供一个,其余的由编译器在后台处理。
猜你喜欢
  • 1970-01-01
  • 2013-09-24
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多