根据模板参数更改属性访问

Change property access based on template argument

本文关键字:属性 访问 参数      更新时间:2023-10-16

我有一个基类,它是一个模板,看起来像这样:

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;
};

这可以使用部分模板特化来实现:

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;
};
这里唯一的问题是你需要为每个专门化复制整个类…除非你想把它放在基类的顶部,例如:
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;
};

是的,这是可能的使用部分专门化。这是否明智是另一个问题——首先,这个解决方案不能扩展,因为你需要2^n的专门化,其中n是你要控制访问的变量的数量。您真的希望类的接口根据模板参数的值而改变吗?

看起来你在创造一些难以维护、难以理解和过于聪明的东西。

然而,如果你觉得这是个好主意,你可以这样做:

template <typename T, bool publicBar=true>
class Foo
{
public:
  T bar;
};
template <typename T>
class Foo<T,false>
{
protected:
  T bar;
};

是的,使用显式类模板特化:

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
}

似乎是一个非常糟糕的主意,虽然。你为什么要这么做?

我认为您可以通过模板专门化来做到这一点。完全未经测试的代码。

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的解决方案可能更易于维护。

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,而只需定义一次。