我正在尝试编写一个函数,该函数接受具有特定模板值的抽象类型,但也具有一个接受其他类型的泛型函数。如我的示例代码所示。
我已经将示例代码简化为必要的部分,因此您可以更好地了解我要问的问题:
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次,而专用运算符将被调用一次。但是它从不叫专业操作员。
有什么我想念的吗?
答案 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&);