Изменить доступ к свойству на основе аргумента шаблона - PullRequest
7 голосов
/ 11 октября 2011

У меня есть базовый класс, который представляет собой шаблон, который выглядит следующим образом:

template <typename T>
class Foo
{
public:
    T bar;
};

Что я хотел бы сделать, это ввести аргумент шаблона, который можно использовать для управления режимом доступа члена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;
};

Ответы [ 5 ]

11 голосов
/ 11 октября 2011

Это можно сделать, используя частичную специализацию шаблона:

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;
};
3 голосов
/ 11 октября 2011

Да, это возможно с частичной специализацией.Является ли это целесообразным, это другой вопрос - для начала, это решение не масштабируется, поскольку вам нужно 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 голосов
/ 11 октября 2011

Да, используя явную специализацию шаблона класса:

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
}

Впрочем, похоже, это очень плохая идея.Почему вы хотите?

1 голос
/ 12 октября 2011

Как насчет

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 количество раз, а только один раз.

1 голос
/ 11 октября 2011

Я думаю, вы могли бы сделать это со специализацией шаблона. Полностью непроверенный код.

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, вероятно, будет более удобным в долгосрочной перспективе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...