Было бы хорошо, если бы был способ передать void
или 'something
', чтобы при объявлении члена класса следующим образом: T setFunction
; компилятор просто удаляет его из класса.
Насколько я понимаю, когда вы выполняете частичную специализацию , вам даже не нужно объявлять setFunction
вообще.
Ниже приведен пример кода, в котором первая специализация
template <typename Getter, typename Setter>
class MyClass final{};
обрабатывает случаи, когда вы предоставляете Getter
и Setter
, а вторая - ситуация без сеттера .
template <typename Getter>
class MyClass<Getter, std::nullptr_t> final
К сожалению, вам все равно нужно указать второй аргумент (т.е. std::nullptr_t{}
), чтобы выбрать правильную специализацию.
( Посмотреть живую демонстрацию онлайн )
#include <iostream>
#include <cstddef> // std::nullptr_t
template <typename Getter, typename Setter>
class MyClass final
{
Getter mGetFunction;
Setter mSetFunction;
using ReType = decltype(mGetFunction());
static_assert(std::is_invocable_v<decltype(mGetFunction)>, " Getter is not callable!");
static_assert(std::is_invocable_v<decltype(mSetFunction), ReType>, " Setter is not callable!");
public:
MyClass(Getter mGetFunction, Setter mSetFunction) noexcept
: mGetFunction{ mGetFunction }
, mSetFunction{ mSetFunction }
{}
void set(ReType value) const noexcept {
mSetFunction(value);
std::cout << "Setter called\n";
}
};
template <typename Getter>
class MyClass<Getter, std::nullptr_t> final
{
Getter mGetFunction;
using ReType = decltype(mGetFunction());
static_assert(std::is_invocable_v<decltype(mGetFunction)>, " Getter is not callable!");
public:
MyClass(Getter mGetFunction, std::nullptr_t) noexcept
: mGetFunction{ mGetFunction }
{}
void set(ReType value) const noexcept {
std::cout << "Object has no setter\n";
}
};
int main()
{
MyClass foo{
[]() { return 7; },
[](int val) { std::cout << "You have set the value\n"; }
};
foo.set(1);
//unfortunately, needed to pass second argument for class instantiation
MyClass foo2([]() {return 7; }, std::nullptr_t{});
foo2.set(1);
}