, я хочу иметь шаблонную функцию, которая принимает унарные указатели на функции-члены экземпляра некоторого универсального типа. Моя проблема заключается в том, что я должен поддерживать функции-члены void (T val) и void (const T & val).
Я написал одну шаблонную функцию для каждого случая, и она отлично работает, но это приводит к дублированию кода, посколькуфункциональная логика полностью одинакова. (Я нашел нечто совершенно похожее здесь: Функция, принимающая и указатель на функцию-член, и указатель на константную функцию-член , но я не вижу окончательного решения).
Пример сущностиУ меня есть это:
using UserAddress = std::string;
class User
{
private:
int mHeight;
UserAddress mAddress;
public:
void SetHeight(int height){mHeight = height;}
void SetAddress(const UserAddress& address){mAddress = address;}
};
где UserAddress - это какой-то тяжелый тип, который я хочу передать по ссылке.
Моя функция шаблона выглядит так:
template <typename TPersistentObject>
class Persistence
{
private:
std::map<std::string, std::function<void(User*)>> mSetterOfProperty;
template <typename TPersistentObject, typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(TPropertyValue), std::function<TPropertyValue(void)> dataReader)
{
mSetterOfProperty[propertyName] =
[propertySetter, columnDataReader](TPersistentObject* persistentObject)
{
(persistentObject->*propertySetter)(dataReader());
};
}
};
/// Const& implementation leading to code duplication
template <typename TPersistentObject, typename TPropertyValue>
void DefinePropertySettingMethod(const std::string& propertyName,
void (TPersistentObject::*propertySetter)(const TPropertyValue&), std::function<TPropertyValue(void)> dataReader)
{
...
}
};
Isесть какой-то способ определить эту функцию один раз и сказать:
int main()
{
auto intDataReader = []() {
return 1;
};
auto stringDataReader = []() {
return UserAddress("Next Door");
};
Persistence p;
p.DefinePropertySettingMethod<User,int>("Height", &User::SetHeight, intDataReader);
p.DefinePropertySettingMethod<User,UserAddress>("Address", &User::SetAddress, stringDataReader);
}