Есть ли способ в C ++ для обеспечения вызовов функций во время компиляции таким образом, что этот вызов будет разрешен:
obj.reset().setParam1(10).setParam2(20);
но этот не удастся скомпилировать:
obj.reset().setParam1(10);
Я хочу избежать установки всех параметров в одной функции, так как их слишком много для установки; поэтому я предпочитаю использовать что-то похожее на именованные параметры идиома.
РЕДАКТИРОВАТЬ: Альтернативный синтаксис может быть:
obj.reset(setParam1(10), setParam2(20));
или же
obj.reset(setParam1(10).setParam2(20));
Поскольку желаемое поведение должно присутствовать во время компиляции, оно должно быть реализовано в системе типов. Насколько я понимаю, это невозможно в C ++ — идиома именованных параметров опирается на функции-установщики, имеющие одинаковый возвращаемый тип (а именно тип вызываемого объекта), поэтому вызовы определенных методов не могут быть предотвращены.
Я приведу вам пример того, как вы делаете это с двумя указанными вами параметрами. Если вам нужно больше, нужно больше работать. Если иерархия требований между параметрами становится слишком сложной, вам может быть сложно структурировать ваши классы, но здесь это так:
class Obj {
Obj2 setParam2(int v);
}
class Obj2: public Obj {
Obj2 setParam1(int v);
}
int main() {
Obj obj;
obj.setParam2(10); // possible
obj.setParam2(10).setParam1(20); // possible
obj.setParam1(20); // not possible
obj.setParam1(20).setParam2(10); // unfortunately not possible
// Edit: one more limitation- consecutive calls are not possible,
// you must chain
obj.setParam2(20);
obj.setParam1(10); // problem
}
Лучшее, что я мог сделать, чтобы предоставить оба именованных параметра и обеспечить инициализацию всех их, это это.
template<typename T>
struct Setter
{
Setter(const T ¶m) : ref(param) {}
const T &ref;
};typedef Setter<int> Param1;
typedef Setter<std::string> Param2;struct CObj
{
void reset(const Param1 &A, const Param2 &B) {
setParam1(A.ref); setParam2(B.ref); }
void setParam1(int i) { param1 = i; }
void setParam2(const std::string &i) { param2 = i; }
int param1;
std::string param2;
};int main()
{
CObj o;
o.reset(Param1(10), Param2("hehe"));
}