为了避免重复类似的函数定义,我使用了一个事实,即隐藏了具有相同名称的继承成员,并且可以使用特定的基类限定符来选择/区分:
#include <type_traits>
template<template<class, class> class CreatePolicy, class Base, class... Derived>
class factory : public CreatePolicy<Base, Derived>...
{
public:
template
<
class T,
std::enable_if_t
<
!std::is_same<Base, T>::value && std::is_base_of<Base, T>::value, int
> = 0
>
std::unique_ptr<Base> create() noexcept( noexcept( CreatePolicy<Base, T>::create() ) )
{
return CreatePolicy<Base, T>::create();
}
};
使用它看起来像这样:
#include <memory>
#include <cassert>
template<class Base, class Derived>
struct create_t
{
auto create()
{
return std::make_unique<Derived>();
}
};
struct base
{
virtual void print() const noexcept
{
std::cout << "base\n";
}
};
struct derived : public base
{
virtual void print() const noexcept override
{
std::cout << "derived\n";
}
};
int main()
{
factory<create_t, base, derived> f;
auto d = f.create<derived>();
d->print();
}
虽然这在VC ++ 2015下编译,但由于noexcept
create()
的{{1}}规范,GCC5.1给出了这个错误:
..\main.cpp|20|error: cannot call member function 'auto create_t<T>::create() [with T = derived]' without object|
如何进行编译?
答案 0 :(得分:1)
调用基类的成员函数的语法Auto
仅在成员函数体内有效。这特别排除了base_class::method(...)
规范中出现的未评估上下文。然而,这些背景的美妙之处在于它们只是:没有评估。所以你可以以某种方式得到你的类的实例并调用该方法。执行此操作的标准方法是使用noexcept
:
std::declval
答案 1 :(得分:0)
std::unique_ptr<Base> create() noexcept( noexcept( std::declval<CreatePolicy<Base, T>&>().create() ) )
您只能在方法体内获得隐式this->
。 Msvc经常错误地模板扩展,所以除非另有证明,否则我会认定他们有罪。