如何使用 Nested-Function-Type 作为函数参数? C++
How To Use Nested-Function-Type As The Function Parameter? C++
问题
void function(InnerType const& inputs) {
struct InnerType {
// All the function required parameters
};
}
是否可以修复有关函数参数类型的编译器错误?
可能的解决方案
struct InnerType;
void function(InnerType const& inputs) {
struct InnerType {
};
}
但是当我们尝试使用它时它失败并出现 'Incomplete Type' 错误。
用法
在我最近的项目中,我要处理很多C API包括第三方库和内核API。
- 首先我尝试包装这些函数,但很快我想出了很多重复的代码来处理琐碎的事情(比如检查 API 先决条件,其中一些在不同的 [=61] 下具有相同的代码=]),
- 然后我尝试用模板编程把条件逻辑隐藏在模板下
- 没过多久我就为一个任务(删除重复)想出了很多不可读的模板代码。
所以我认为,如果我们可以有一个嵌套函数类型,我们可以轻松地将 API 参数包装在 C++ 函数中,以避免使用重复代码的全新 class
。
我的限制
- 我无法在函数的同一命名空间中定义
struct
。因为所有 API 处理程序都在同一个文件中定义,所以很难选择唯一的名称。
- 我无法为每个处理程序创建一个文件,因为我们已经有很多文件了。
我的优先事项
- 可读性
- 可维护性
- 强类型(用于处理 C APIs)
例子
Expected<ReturnType> GetDataFrom(FunctionParamType const& inputs) {
struct FunctionParamType {
String string;
Integer index;
};
ThrowExceptionOnEmptyString(inputs.string, "Missed Something");
ThrowExceptionOnZeroInteger(inputs.index, "Wrong Index");
// Call The API
}
// Usage
auto const result = GetDataFrom({.string = "something", .index = 1});
而不是:
class DataApi {
public:
void setString(String const& string) {
ThrowExceptionOnEmptyString(string, "Missed Something");
string_ = string;
}
void setInteger(Integer const& interger) {
ThrowExceptionOnZeroInteger(integer, "Wrong Index");
integer_ = integer;
}
String getString() const noexcept { return string_; }
Integer getInteger() const noexcept { return integer_; }
DataApi(String const& string, Integer const& integer)
: string_(string), integer_(integer) {
ThrowExceptionOnEmptyString(string, "Missed Something");
ThrowExceptionOnZeroInteger(integer, "Wrong Index");
}
DataApi() = default;
Expected<ReturnType> execute() {
// Call The API
}
private:
String string_;
Integer integer_;
};
// Usage
auto const result = DataApi("Something", 1).execute();
这种方法怎么样:
namespace some_api_function {
struct parameter_type {
...
};
struct return_type {
...
};
return_type call(parameter_type p) {
...
}
}
唯一更改的名称是周围命名空间的名称。 parameter_type
、call
和 return_type
在各种 API 包装器中保持不变。
顺便说一句:您为参数结构验证设置器的方法是有缺陷的。特别是,如果您不从构造函数开始就建立该保证,则不能保证参数正确。此外,如果两个参数的正确性相互依赖,则该方法不适用于单独的设置器。
相反,请考虑再编写两个函数 validate()
,您首先调用参数,最后调用结果。这也是在代码中清楚记录这些要求的好方法。
问题
void function(InnerType const& inputs) {
struct InnerType {
// All the function required parameters
};
}
是否可以修复有关函数参数类型的编译器错误?
可能的解决方案
struct InnerType;
void function(InnerType const& inputs) {
struct InnerType {
};
}
但是当我们尝试使用它时它失败并出现 'Incomplete Type' 错误。
用法
在我最近的项目中,我要处理很多C API包括第三方库和内核API。
- 首先我尝试包装这些函数,但很快我想出了很多重复的代码来处理琐碎的事情(比如检查 API 先决条件,其中一些在不同的 [=61] 下具有相同的代码=]),
- 然后我尝试用模板编程把条件逻辑隐藏在模板下
- 没过多久我就为一个任务(删除重复)想出了很多不可读的模板代码。
所以我认为,如果我们可以有一个嵌套函数类型,我们可以轻松地将 API 参数包装在 C++ 函数中,以避免使用重复代码的全新 class
。
我的限制
- 我无法在函数的同一命名空间中定义
struct
。因为所有 API 处理程序都在同一个文件中定义,所以很难选择唯一的名称。 - 我无法为每个处理程序创建一个文件,因为我们已经有很多文件了。
我的优先事项
- 可读性
- 可维护性
- 强类型(用于处理 C APIs)
例子
Expected<ReturnType> GetDataFrom(FunctionParamType const& inputs) {
struct FunctionParamType {
String string;
Integer index;
};
ThrowExceptionOnEmptyString(inputs.string, "Missed Something");
ThrowExceptionOnZeroInteger(inputs.index, "Wrong Index");
// Call The API
}
// Usage
auto const result = GetDataFrom({.string = "something", .index = 1});
而不是:
class DataApi {
public:
void setString(String const& string) {
ThrowExceptionOnEmptyString(string, "Missed Something");
string_ = string;
}
void setInteger(Integer const& interger) {
ThrowExceptionOnZeroInteger(integer, "Wrong Index");
integer_ = integer;
}
String getString() const noexcept { return string_; }
Integer getInteger() const noexcept { return integer_; }
DataApi(String const& string, Integer const& integer)
: string_(string), integer_(integer) {
ThrowExceptionOnEmptyString(string, "Missed Something");
ThrowExceptionOnZeroInteger(integer, "Wrong Index");
}
DataApi() = default;
Expected<ReturnType> execute() {
// Call The API
}
private:
String string_;
Integer integer_;
};
// Usage
auto const result = DataApi("Something", 1).execute();
这种方法怎么样:
namespace some_api_function {
struct parameter_type {
...
};
struct return_type {
...
};
return_type call(parameter_type p) {
...
}
}
唯一更改的名称是周围命名空间的名称。 parameter_type
、call
和 return_type
在各种 API 包装器中保持不变。
顺便说一句:您为参数结构验证设置器的方法是有缺陷的。特别是,如果您不从构造函数开始就建立该保证,则不能保证参数正确。此外,如果两个参数的正确性相互依赖,则该方法不适用于单独的设置器。
相反,请考虑再编写两个函数 validate()
,您首先调用参数,最后调用结果。这也是在代码中清楚记录这些要求的好方法。