通过模板和 SFINAE 支持多个 class 接口
Supporting multiple class interfaces through templating and SFINAE
我有一个 class 派生自第三方库中提供的 class。
在第三方库的不同版本之间,他们将其中一个 classes 中的成员从私有提升为 public,但在此过程中,他们弃用了一种访问该成员的方法。示例:
// Old class
class A
{
public:
int &GetA() { return a;}
private:
int a;
};
// NewClass
class A
{
public:
int a;
};
我的代码使用了 A
的一个实例,但我希望我的代码可以使用任一版本,以防有人没有更新库。
class B
{
public:
int & ReturnA() { return GetInnards(m_a);}
private:
A m_a;
// If m_a has a GetA member function call this:
template(typename aType)
int & GetInnards(aType &a) { return a.GetA(); }
// If m_a does not have an GetA() member function, call this:
template(typename aType)
int & GetInnards(aType &a) { return a.m_a; }
};
似乎我应该可以使用 SFINAE,但我缺少一些东西。
另外,我无法用 #ifdef
测试任何东西,所以我不能走那条路。我需要检测方法是否存在,或者成员是否为 public.
嗯...给定几个模板函数如下
template <typename A>
constexpr auto hasGetA (A const &)
-> decltype( std::declval<A>().GetA(), std::true_type{} );
template <typename ... Ts>
constexpr std::false_type hasGetA (Ts const & ...);
你可以写你的方法
template <typename aType>
auto GetInnards (aType & a)
-> std::enable_if_t<true == decltype(hasGetA(a))::value, int &>
{ return a.GetA(); }
template <typename aType>
auto GetInnards (aType & a)
-> std::enable_if_t<false == decltype(hasGetA(a))::value, int &>
{ return a.a; }
我有一个 class 派生自第三方库中提供的 class。
在第三方库的不同版本之间,他们将其中一个 classes 中的成员从私有提升为 public,但在此过程中,他们弃用了一种访问该成员的方法。示例:
// Old class
class A
{
public:
int &GetA() { return a;}
private:
int a;
};
// NewClass
class A
{
public:
int a;
};
我的代码使用了 A
的一个实例,但我希望我的代码可以使用任一版本,以防有人没有更新库。
class B
{
public:
int & ReturnA() { return GetInnards(m_a);}
private:
A m_a;
// If m_a has a GetA member function call this:
template(typename aType)
int & GetInnards(aType &a) { return a.GetA(); }
// If m_a does not have an GetA() member function, call this:
template(typename aType)
int & GetInnards(aType &a) { return a.m_a; }
};
似乎我应该可以使用 SFINAE,但我缺少一些东西。
另外,我无法用 #ifdef
测试任何东西,所以我不能走那条路。我需要检测方法是否存在,或者成员是否为 public.
嗯...给定几个模板函数如下
template <typename A>
constexpr auto hasGetA (A const &)
-> decltype( std::declval<A>().GetA(), std::true_type{} );
template <typename ... Ts>
constexpr std::false_type hasGetA (Ts const & ...);
你可以写你的方法
template <typename aType>
auto GetInnards (aType & a)
-> std::enable_if_t<true == decltype(hasGetA(a))::value, int &>
{ return a.GetA(); }
template <typename aType>
auto GetInnards (aType & a)
-> std::enable_if_t<false == decltype(hasGetA(a))::value, int &>
{ return a.a; }