【问题标题】:c++ template specialization for base class基类的c ++模板特化
【发布时间】:2014-01-29 17:04:06
【问题描述】:

我想为 BASECLASS 和所有派生类提供一个特殊的格式化程序。我有以下课程:

struct BASECLASS { ... };
struct SPECIALFORMAT : BASECLASS { ... }
struct ANOTHERSPECIALFORMAT : BASECLASS { ... }

template <class T>
struct LISTFORMATTER {
  list<T> l;

  bool format() {

  };
}
bool LISTFORMATTER<BASECLASS>::format() { ... }

LISTFORMATTER<BASECLASS> bcFt;
LISTFORMATTER<SPECIALFORMAT> spFt;
LISTFORMATTER<ANOTHERSPECIALFORMAT> aspFt;

bcFt.format(); // <-- ok
spFt.format(); // <-- Calling standard format(), not specialized
aspFt.format(); // <-- Calling standard format(), not specialized

如何为基类和所有继承类专门化一个方法?

EDIT 最好不要使用 boost。 c++(不是 c++11)

【问题讨论】:

  • this question 的相似性、要求和潜在解决方案几乎相同,即按基类进行专业化。而且你不会喜欢答案。
  • 目前并没有一种简单快速的方法来实现 is_base_of,我可以通过在每个声明中手动指定 true 或 false 来实现。谢谢。

标签: c++ templates template-specialization


【解决方案1】:

首先,您需要is_base_of。如果您不想使用 Boost 或 C++11,请在此处获取: How does `is_base_of` work?

然后,您可以这样做:

template <bool B> struct bool_ {};
// ...
bool format() { do_format(bool_<is_base_of<BASECLASS, T>::value>()); }
bool do_format(bool_<false>) {
  // not inheriting BASECLASS
}
bool do_format(bool_<true>) {
  // inheriting BASECLASS
}

顺便说一句,AFAIK 无法以非侵入方式进行此操作,即只需添加专业化。

编辑:实际上,不用 is_base_of 也可以做到:

// ...
bool format() { do_format((T*)0); }
bool do_format(void*) { /* not inheriting */ }
bool do_format(BASECLASS*) { /* inheriting */ }

这是可行的,因为 derived->base 是比 class->void 更好的转换。

【讨论】:

  • 迄今为止最好的解决方案恕我直言。谢谢塞巴斯蒂安!
  • 好方法,但在链接的问题中,我找不到 is_base_of 的简单实现。目前,@WhozCraig 所说的更接近的方法是在this question
  • 这和库中的is_base_of 一样简单。考虑到极端情况和编译器错误,Boost 的实现要复杂得多。
  • 我想我找到了没有is_base_of的方法。
  • 感谢@SebastianRedl 就像一个魅力。非常聪明。唯一要记住的是,它正在进行额外的堆栈调用,与我的项目无关。
【解决方案2】:

标签调度可能会有所帮助:

struct BASECLASS { };
struct SPECIALFORMAT : BASECLASS { };
struct ANOTHERSPECIALFORMAT : BASECLASS { };

template <typename T>
struct IsDerivedFromBASECLASS {
    static const bool value = false; //std::is_base_of<BASECLASS, T>::value;
};

template <>
struct IsDerivedFromBASECLASS<BASECLASS> { static const bool value = true; };
template <>
struct IsDerivedFromBASECLASS<SPECIALFORMAT> { static const bool value = true; };
template <>
struct IsDerivedFromBASECLASS<ANOTHERSPECIALFORMAT> { static const bool value = true; };


template <class T>
struct LISTFORMATTER {
  //list<T> l;

  bool format();
};

template <typename T, bool IsABASECLASS>
struct helper_format {
    bool operator() (LISTFORMATTER<T>&)
    {
        // default implementation
        return true;
    }
};

template <typename T>
struct helper_format<T, false>
{
    bool operator() (LISTFORMATTER<T>&)
    {
        // specialization implementation
        return false;
    }
};

template<typename T>
bool LISTFORMATTER<T>::format() {
    return helper_format<T, IsDerivedFromBASECLASS<T>::value>(*this);
}

【讨论】:

    【解决方案3】:

    我认为您可以使用 enable_if 和 is_base_of(来自 c++11 或 boost)来做到这一点。

    【讨论】:

    • 是的,对不起,我没有指定:如果可能的话,我不喜欢使用 boost(这是现在唯一需要的地方),它是 c++
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多