我在C ++中玩装饰模式。在像书中那样工作之后,我决定创建一个模板函数(称为“装饰”)来帮助我根据装饰器类,具体类和接口类构造装饰对象。
基本模板功能完美无缺。但后来我决定我也想要一个空的decorator实现,除了调用具体的对象方法之外别无其他。这很有效,我可以坚持这个设计,但是当我使用空的装饰器时,我仍然会有一个虚拟调用,实际上除了调用另一个虚拟方法之外什么也没做。我想避免这种不必要的间接,我决定专门化我的模板函数,以便在使用空装饰器时,它返回未修饰的对象(具体对象)。 我想使用enable_if专门化我的模板函数,但不知何故它不想编译。我一定做错了什么。请帮我。我的代码有什么问题?
#include <iostream>
#include <memory>
#include <type_traits>
using namespace std;
struct IA {
virtual ~IA() {}
virtual void doSth() = 0;
};
struct ConcreteA : public IA
{
void doSth() override
{
cout << "concrete: doSth" << endl;
}
};
struct LoggingDecoratorA : public IA {
LoggingDecoratorA(unique_ptr<IA> pia) : _pia(move(pia)) {}
void doSth() override
{
cout << "calling doSth" << endl;
_pia->doSth();
}
unique_ptr<IA> _pia;
};
struct EmptyDecoratorA : public IA {
EmptyDecoratorA(unique_ptr<IA> pia) : _pia(move(pia)) {}
void doSth() override
{
_pia->doSth();
}
unique_ptr<IA> _pia;
};
void fun(IA* pia)
{
pia->doSth();
}
template<typename Decorator, typename Concrete, typename Interface, typename X = enable_if_t<!is_same<Decorator, EmptyDecoratorA>::value>>
unique_ptr<Interface> decorate()
{
return make_unique<Decorator>((make_unique<Concrete>()));
}
template<typename Decorator, typename Concrete, typename Interface, typename X = void>
unique_ptr<Interface> decorate()
{
return make_unique<Concrete>();
}
int main()
{
auto pia = decorate<LoggingDecoratorA, ConcreteA, IA>();
fun(pia.get());
}
答案 0 :(得分:1)
试试这个:
template<typename Decorator, typename Concrete, typename Interface>
typename enable_if<is_same<Decorator, EmptyDecoratorA>::value, unique_ptr<Interface>>::type
decorate()
{
return make_unique<Decorator>((make_unique<Concrete>()));
}
template<typename Decorator, typename Concrete, typename Interface>
typename enable_if<!is_same<Decorator, EmptyDecoratorA>::value, unique_ptr<Interface>>::type
decorate()
{
return make_unique<Concrete>();
}
答案 1 :(得分:0)
template<typename Decorator, typename Concrete, typename Interface,
typename X = enable_if_t<!is_same<Decorator, EmptyDecoratorA>::value>>
unique_ptr<Interface> decorate()
{
return make_unique<Decorator>((make_unique<Concrete>()));
}
template<typename Decorator, typename Concrete, typename Interface,
typename X = void>
unique_ptr<Interface> decorate()
{
return make_unique<Concrete>();
}
这不是SFINAE的工作方式(默认模板类型参数不是函数签名的一部分,请查看此question以获取更多详细信息)。
您可以按如下方式更改代码:
template<typename Decorator, typename Concrete, typename Interface>
auto decorate() ->
enable_if_t<!is_same<Decorator, EmptyDecoratorA>::value, unique_ptr<Interface>>
{
return make_unique<Decorator>((make_unique<Concrete>()));
}
template<typename Decorator, typename Concrete, typename Interface>
auto decorate() ->
enable_if_t<is_same<Decorator, EmptyDecoratorA>::value, unique_ptr<Interface>>
{
return make_unique<Concrete>();
}
并将std::enable_if_t
移至返回类型。现在正确应用SFINAE,因为返回类型是函数签名的一部分。