在模板类中隐藏成员函数
是否有可能隐藏模板类中的一些成员函数? 让我们想象我们有这样的东西:
template <class T>
class Increment
{
public:
void init(T initValue)
{
mValue = initValue;
}
T increment()
{
++mValue;
}
T increment(T delta)
{
mValue += delta;
}
private:
T mValue;
};
目标是以某种方式使用这个类,在某些情况下,我们只能看到increment()函数,而在其他一些情况下,我们只能看到增量(T)成员函数。 要做到这一点,我可以考虑使用SFINAE:
class MultipleIncrement
{
typedef int MultipleIncrement_t;
};
class SingleIncrement
{
typedef int SingleIncrement_t;
};
template <class T, class Q>
class Increment
{
public:
void init(T initValue)
{
mValue = initValue;
}
T increment(typename Q::SingleIncrement_t = 0)
{
++mValue;
}
T increment(T delta, typename Q::MultipleIncrement_t = 0)
{
mValue += delta;
}
private:
T mValue;
}
然后使用我的模板,例如:
Increment<long, MultipleIncrement>
但是,编译器不让我这样做。 有没有其他方法可行? 如果成员函数实际上是构造函数,它也可以工作吗?
在这种情况下,我宁愿使用模板专业化。 这样的事情能帮助你吗?
struct SingleIncrement;
struct MultipleIncrement;
template <
class T,
class Policy = SingleIncrement // default template param
>
class Increment
{
T mValue;
public:
Increment(T initValue)
: mValue(initValue)
{}
T increment()
{
++mValue;
}
};
// template specialization for MultipleIncrement
template <class T>
class Increment<T,MultipleIncrement>
{
T mValue;
public:
Increment(T initValue)
: mValue(initValue)
{}
T increment(T delta)
{
mValue += delta;
}
};
模板专业化很好。 继承听起来更好。 你有没有考虑在继承的基类上进行模板化? (或者现在这被认为是一个人造人?)
#define SHOW(X) cout << # X " = " << (X) << endl
template <class T>
class A
{
public:
void foo(T t) {SHOW(t); }
};
template <class T, class BASE>
class B : public BASE
{
public:
void bar(T t) {SHOW(t); }
};
int
main()
{
B<int,A<int> > b;
b.foo(1);
b.bar(2);
}
这是如何实现这一目标的MWE:
#include <iostream>
using namespace std;
struct multi;
struct single;
template<class T, class Q>
struct dummy {
dummy(T value) : m_value(value) { }
// using enable_if_t in template argument
template<class _Q = Q, enable_if_t<is_same<_Q, single>::value && is_same<_Q, Q>::value, int> = 1>
T increment() { return ++m_value; }
// using enable_if_t in method return type
template<class _Q = Q>
enable_if_t<is_same<_Q, multi>::value && is_same<_Q, Q>::value, T>
//enable_if_t<is_same<_Q, multi>::value, T> // (*)
increment(T delta) { return (m_value += delta); }
T m_value;
};
int main() {
dummy<double, multi> m(47.10);
//cout << m.increment() << endl; // error as expected
cout << m.increment(.01) << endl;
dummy<int, single> s(41);
cout << s.increment() << endl;
cout << s.increment<single>() << endl;
//cout << s.increment(1) << endl; // error as expected
//cout << s.increment<multi>(1) << endl; // not an error when using (*)
}
产量
使用c++ (Debian 6.2.1-5) 6.2.1 20161124
这产生:
47.11
42
43
精
我们需要对这些方法进行模板来完成SFINAE。 我们不能使用类似的东西
std::enable_if_t<std::is_same<_Q, multiple_increment>::value, T> increment() ...
因为在实例化模板dummy<T, single_increment>
时失败,而不是在替换方法模板参数时失败。
此外,我们希望用户能够使用这些方法,而无需实际提供方法模板参数。 所以我们将方法模板参数_Q
默认为Q
最后,即使在提供方法模板参数时,为了在使用不需要的方法时真的强制编译器错误,只有方法模板参数_Q
实际上与相应的类模板参数Q
同时,才会使用enable_if_t
方法。
上一篇: Hiding member functions in a template class
下一篇: How do I configure log4j per deployed application in Glassfish 3?