我有一个基类,它是一个如下所示的模板:
template <typename T>
class Foo
{
public:
T bar;
};
我想要做的是介绍一个模板参数,该参数可用于控制成员栏的访问模式。
这样的事情:
template <typename T,bool publicBar=true>
class Foo
{
public:
// If publicBar is false, insert protected: here
T bar;
};
这可能吗?
感谢。
编辑: 许多人这么问,对于那些为什么我这样做有趣的人,这是我的真实代码!
// Class used for automatic setter/getter generation.
template <typename T,publicSetter=true>
class Property
{
public:
Property(){}
Property(T value):mObject(object){}
T operator()()const
{
return mObject;
}
public: // This is where I want the protected:
virtual void operator()(T newObject)
{
this->mObject = newObject;
}
private:
T mObject;
};
答案 0 :(得分:11)
这可以使用部分模板专业化来完成:
template <typename T,bool publicBar>
class Foo
{
};
template <typename T>
class Foo<T,true>
{
public:
T bar;
};
template <typename T>
class Foo<T,false>
{
protected:
T bar;
};
这里唯一的问题是你需要为每个专业化复制整个类... UNLESS 你想在基类之上进行复制,例如:
template <typename T>
class FooBase
{
//the goods go here
};
template <typename T,bool publicBar>
class Foo : public FooBase<T>
{
};
template <typename T>
class Foo<T,true> : public FooBase<T>
{
public:
T bar;
};
template <typename T>
class Foo<T,false> : public FooBase<T>
{
protected:
T bar;
};
答案 1 :(得分:3)
是的,这是可能的使用部分特化。是否可取是另一个问题 - 首先,这个解决方案不能扩展,因为你需要2 ^ n个特化,其中n是你控制访问的变量数。你真的希望你的类的接口根据模板参数的值来改变吗?
看起来你正在创造一些难以维护,难以理解和过于聪明的东西。
尽管如此,如果您认为这是一个好主意,请按照以下方式进行操作:
template <typename T, bool publicBar=true>
class Foo
{
public:
T bar;
};
template <typename T>
class Foo<T,false>
{
protected:
T bar;
};
答案 2 :(得分:2)
是的,使用显式类模板专业化:
template<bool B> class Foo;
template<> class Foo<true>
{
public:
int n_;
};
template<> class Foo<false>
{
protected:
int n_;
};
int main()
{
Foo<true> fa;
fa.n_;
Foo<false> fb;
fb.n_; // ERROR: protected
}
但是,这似乎是一个非常糟糕的主意。你为什么要这样做?
答案 3 :(得分:1)
我认为你可以通过模板专业化来做到这一点。完全未经测试的代码。
template <typename T,bool publicBar=true>
class Foo
{
public:
// If publicBar is false, insert protected: here
T bar;
};
template <typename T, false>
class Foo
{
protected:
// If publicBar is false, insert protected: here
T bar;
};
但是要真的考虑一下你为什么要这样做。 public
数据对于封装非常危险,而protected
几乎就是这样。能够利用客户端API的解决方案在长期内可能更易于维护。
答案 4 :(得分:1)
怎么样
template<typename T>
struct FooBase {
T bar;
};
template<typename T, bool publicBar>
class Foo : public FooBase<T> {};
template<typename T>
class Foo<T, false> : protected FooBase<T> {};
通过这种方式,您不必多次定义bar
,而只需定义一次。