在C++中,强制执行函数调用的编译时检查

4

在C++中是否有一种方法可以强制在编译时进行函数调用,以使得这个调用将被允许:

obj.reset().setParam1(10).setParam2(20);

但这个代码将无法编译通过:
obj.reset().setParam1(10);

我希望避免在一个函数中设置所有参数,因为有太多需要设置的参数;所以我更喜欢使用类似于命名参数习语的东西。
编辑:替代语法可以是:
obj.reset(setParam1(10), setParam2(20));

或者

obj.reset(setParam1(10).setParam2(20));

1
我真的不认为你能对此做任何事情。也许通过一些模板魔法,你可以实现类似的行为,但是语法不同。你可以告诉我你为什么需要它吗?也许我们可以通过更智能的设计找到解决方案。:P - Melkon
@Melkon 目标是强制类用户设置所有必需的参数,而不强制他使用一个带有十几个参数的 setter 函数。 - jackhab
1
我不太明白那个语法的意义是什么。我以为你想要的是有5个参数,但至少需要定义其中2个。实际上,与设置所有参数的一个函数相比,链接函数更慢且更难阅读。您还可以将所有输入参数存储在结构体中,并定义一个需要该结构体的单个函数。为什么这种语法很重要呢? - Melkon
1
定义一个包含所有参数的结构体,并使用该结构体作为参数来设置方法。删除单个setParam方法。 - Alex F
重置可以为所有内容提供默认值,或者您可以在使用它们之前每次检查它们是否已初始化。 - Melkon
显示剩余2条评论
3个回答

2

如果您只提供了两个参数,我可以给您举个例子来说明如何实现。如果需要更多参数,则需要更多的工作。如果参数之间的需求层次结构变得过于复杂,您可能会发现很难构建您的类,但是下面是一个示例:

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
}

有趣的解决方案,但类型定义强制执行一系列固定的setter调用。 - Codor
或者使用多个“固定的setter调用序列”,如果需要更多参数和更多类,则可以使用此概念。一些库使用此概念提供可链接的API,易于使用。 - mostruash
在我的情况下,obj.setParam2(10) 是禁止的。必须调用所有设置器。顺序不重要。我在考虑将 obj1-obj2-objn 链接起来,然后更改重置函数以接收 objn 参数:obj.reset(setParam1(10).setParam(20)),但是 obj 引用如何进入 setParam1() 函数呢?我有点困惑。 - jackhab
你可以定义返回类型为 Objreset()。如果你不知道如何实现它,请告诉我,我可以帮忙。 - mostruash
哦,等等,如果必须设置所有参数,这对你来说不起作用。它只允许您限制可链接函数调用的顺序。 - mostruash

2

由于所需行为必须在编译时存在,因此它需要在类型系统中实现。据我所知,在C++中这是不可能的-命名参数惯用语依赖于设置函数具有相同的返回类型(即调用对象的类型),因此无法防止对某些方法的调用。


0

为了提供命名参数并强制初始化所有参数,我能做的最好的事情是这样的。

template<typename T>
struct Setter
{
    Setter(const T &param) : 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"));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接