具有广义参数的上下文中具有抽象参数的特殊函数

时间:2019-01-07 16:23:23

标签: c++

我正在尝试编写一个函数,该函数接受具有特定模板值的抽象类型,但也具有一个接受其他类型的泛型函数。如我的示例代码所示。

我已经将示例代码简化为必要的部分,因此您可以更好地了解我要问的问题:

template <typename ValTy, typename RootTy=void>
class ITransformer
{
private:
  int sz;
  ValTy* inBuffer[1000];

public:
  using SelfType = typename std::conditional<std::is_void<RootTy>::value, ITransformer<ValTy>, RootTy>::type;

  template <typename OtherRoot>
  SelfType &operator <<(const ITransformer<ValTy, OtherRoot> &other) {
    std::cout << "Used specialized operator\n";
    memcpy(&this->inBuffer[this->sz], other.inBuffer, other.size);
    this->sz += other.size;
    return *static_cast<SelfType*>(this);
  }
  // default operator, accepts all remaining types
  template <typename T>
  SelfType &operator <<(const T) {
    std::cout << "Used default operator\n";
    return *static_cast<SelfType*>(this);
  }
};

class StringTransformer : public ITransformer<char, StringTransformer>
{
public:
  StringTransformer() { }
};


int main() {
  StringTransformer() << false << (StringTransformer() << "value") << 12;
  std::cout << "End";
}

在主函数中,我希望默认运算符被调用3次,而专用运算符将​​被调用一次。但是它从不叫专业操作员。

有什么我想念的吗?

1 个答案:

答案 0 :(得分:0)

致电StringTransformer() << StringTransformer()

2个可行的重载是:

  • template <typename OtherRoot> SelfType &operator <<(const ITransformer<ValTy, OtherRoot> &)(#1)

  • template <typename T> SelfType &operator <<(const T)(#2)

(#1)需要派生到基数转换,而(#2)是完全匹配,因此是首选。

您可能将SFINAE设置为(#2),以不匹配ITransformer的派生类

首先,创建特征:

template <typename Val, typename Root>
std::true_type derived_from_ITransformer_impl(const ITransformer<Val, Root>*);
std::false_type derived_from_ITransformer_impl(...);

template <typename T>
using is_derived_from_ITransformer =
    decltype(derived_from_ITransformer_impl(std::declval<T*>()));

然后

template <typename T, std::enable_if_t<!is_derived_from_ITransformer<T>(), int> = 0>
SelfType &operator <<(const T&);

Demo