Специализация шаблона C ++ для предоставления / добавления различных функций-членов

Я немного экспериментирую с чертами типов и специализацией шаблонов. Например:

enum TestEnum
{
VALUE0 = 0,
VALUE1 = 1,
VALUE2 = 2
//... And so on...
};

template<int Value>
class cTestClass;

//specializations
template<>
class cTestClass<VALUE0>
{
static int GetVal() { return VALUE0; }
};

template<>
class cTestClass<VALUE1>
{
static int GetVal() { return VALUE1; }
};

template<>
class cTestClass<VALUE2>
{
static int GetVal() { return VALUE2; }
};

typedef cTestClass<VALUE0> cClassVal0; //(1)
typedef cTestClass<VALUE1> cClassVal1; //(2)
typedef cTestClass<VALUE2> cClassVal2; //(3)

//Later in the code
template<int Value>
cTestClass<Value>* Create()
{
return new cTestClass<Value>(/*..*/);
}

//And using the upper function
cClassVal2* pTestClass = Create<VALUE2>();

Это работает абсолютно нормально. Цель состоит в том, чтобы предоставить пользователям интерфейса возможность не иметь дело с шаблонами и параметрами шаблона (хорошо, кроме использования Создайте()). Это причина для typedefs внизу кода.

Нет, вот чего я хочу добиться:
cTestClass должен иметь одну переменную-член, которая доступна через функции-члены. При определенных обстоятельствах я либо хочу, чтобы пользователь мог изменять переменную-член, либо не изменять переменную-член. Таким образом, в основном это означает две функции-члена, одна из которых возвращает член в виде константной ссылки (не модифицируемой) или не константной (модифицируемой). Проблема в том, что, если обе эти функции-члены предоставлены, у пользователя всегда есть возможность изменить переменную-член. Поэтому я хочу выбрать подходящую функцию-член во время компиляции и просто предоставить одну правильную функцию-член для пользователя.

Единственное решение, которое я нашел, выглядит в основном так:

template<int Value, bool ConstAccess>
class cTestClass;

//specializations
template<>
class cTestClass<VALUE0, true>
{
const std::string& get() const
{
return m_strName;
}

static int GetVal() { return VALUE0; }

private:
std::string m_strName;
};

template<>
class cTestClass<VALUE0, false>
{
std::string& get()
{
return m_strName;
}

static int GetVal() { return VALUE0; }

private:
std::string m_strName;
};

//For every upcoming cTestClass two specializations

typedef cTestClass<VALUE0, true> cConstObjectVal0;
typedef cTestClass<VALUE0, false> cObjectVal0;
//And for the rest...

Помимо того факта, что это действительно кажется ненужным дублированием кода, я всегда должен указывать два typedef для каждого возможного VALUE. Но пользователь не должен сталкиваться с этим выбором, он всегда должен иметь возможность просто использовать типы, как указано выше (см. 1, 2, 3).

Это вообще возможно?

Я немного погуглил и придумал следующий сайт: ACCU :: Введение в черты C ++.
Это объяснение кажется подходящей схемой, но я действительно не могу собрать все воедино.
Другая возможность, которую я нашел, описана здесь: C ++ Шаблон специализации, чтобы обеспечить дополнительную функцию-член? Было бы возможно просто добавить одну функцию, но это все равно не решило бы мою проблему с typedef.

2

Решение

Мы можем попытаться нанять SFINAE:

typedef char True;
typedef long False;

template <typename VALUE0, typename IsConst>
class cTestClass
{
public:

template <typename T, T> struct TypeCheck {};

const std::string& get(TypeCheck<IsConst, True >* dummy = NULL);
std::string& get(TypeCheck<IsConst, False>* dummy = NULL);
}

typedef cTestClass<VALUE0, True>  cConstObjectVal0;
typedef cTestClass<VALUE0, False> cObjectVal0;

Я еще не пытался скомпилировать его, но общий принцип состоит в том, чтобы предотвратить одну из функций для правильной компиляции. SFINAE В принципе, компилятор просто выбросит не ту версию.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]