C ++ cung cấp các lựa chọn thay thế riêng để đạt được chức năng của các tham số được đặt tên:
Cấu trúc bao bọc . Xác định các tham số tùy chọn của bạn dưới dạng các trường của một cấu trúc.
struct foo_args {
const char* title = "";
int year = 1900;
float percent = 0.0;
};
void foo(int a, int b, const foo_args& args = foo_args())
{
printf("title: %s\nyear: %d\npercent: %.2f\n",
args.title, args.year, args.percent);
}
int main()
{
foo_args args;
args.title = "foo title";
args.percent = 99.99;
foo(1, 2, args);
/* Note: in pure C brace initalizers could be used instead
but then you loose custom defaults -- non-initialized
fields are always zero.
foo_args args = { .title = "foo title", .percent = 99.99 };
*/
return 0;
}
Đối tượng proxy . Các đối số được lưu trữ trong một cấu trúc tạm thời có thể được sửa đổi với setters chuỗi.
struct foo {
// Mandatory arguments
foo(int a, int b) : _a(a), _b(b) {}
// Optional arguments
// ('this' is returned for chaining)
foo& title(const char* title) { _title = title; return *this; }
foo& year(int year) { _year = year; return *this; }
foo& percent(float percent) { _percent = percent; return *this; }
// Do the actual call in the destructor.
// (can be replaced with an explicit call() member function
// if you're uneasy about doing the work in a destructor)
~foo()
{
printf("title: %s\nyear: %d\npercent: %.2f\n", _title, _year, _percent);
}
private:
int _a, _b;
const char* _title = "";
int _year = 1900;
float _percent = 0.0;
};
int main()
{
// Under the hood:
// 1. creates a proxy object
// 2. modifies it with chained setters
// 3. calls its destructor at the end of the statement
foo(1, 2).title("foo title").percent(99.99);
return 0;
}
Lưu ý : bản tóm tắt có thể được trừu tượng hóa thành một macro với chi phí dễ đọc:
#define foo_optional_arg(type, name, default_value) \
public: foo& name(type name) { _##name = name; return *this; } \
private: type _##name = default_value
struct foo {
foo_optional_arg(const char*, title, "");
foo_optional_arg(int, year, 1900);
foo_optional_arg(float, percent, 0.0);
...
Chức năng biến thể . Điều này rõ ràng là không an toàn và đòi hỏi kiến thức về các chương trình khuyến mãi để có được quyền. Tuy nhiên, nó có sẵn trong C thuần nếu C ++ không phải là một tùy chọn.
#include <stdarg.h>
// Pre-defined argument tags
enum foo_arg { foo_title, foo_year, foo_percent, foo_end };
void foo_impl(int a, int b, ...)
{
const char* title = "";
int year = 1900;
float percent = 0.0;
va_list args;
va_start(args, b);
for (foo_arg arg = (foo_arg)va_arg(args, int); arg != foo_end;
arg = (foo_arg)va_arg(args, int))
{
switch(arg)
{
case foo_title: title = va_arg(args, const char*); break;
case foo_year: year = va_arg(args, int); break;
case foo_percent: percent = va_arg(args, double); break;
}
}
va_end(args);
printf("title: %s\nyear: %d\npercent: %.2f\n", title, year, percent);
}
// A helper macro not to forget the 'end' tag.
#define foo(a, b, ...) foo_impl((a), (b), ##__VA_ARGS__, foo_end)
int main()
{
foo(1, 2, foo_title, "foo title", foo_percent, 99.99);
return 0;
}
Lưu ý : Trong C ++, điều này có thể được thực hiện an toàn kiểu với các mẫu matrixdic. Chi phí hoạt động trong thời gian chạy sẽ không còn chi phí cho thời gian biên dịch chậm và phình nhị phân.
boost :: tham số . Vẫn là một thư viện của bên thứ ba, mặc dù lib được thiết lập nhiều hơn một số repo github tối nghĩa. Nhược điểm: nặng mẫu.
#include <boost/parameter/name.hpp>
#include <boost/parameter/preprocessor.hpp>
#include <string>
BOOST_PARAMETER_NAME(foo)
BOOST_PARAMETER_NAME(bar)
BOOST_PARAMETER_NAME(baz)
BOOST_PARAMETER_NAME(bonk)
BOOST_PARAMETER_FUNCTION(
(int), // the return type of the function, the parentheses are required.
function_with_named_parameters, // the name of the function.
tag, // part of the deep magic. If you use BOOST_PARAMETER_NAME you need to put "tag" here.
(required // names and types of all required parameters, parentheses are required.
(foo, (int))
(bar, (float))
)
(optional // names, types, and default values of all optional parameters.
(baz, (bool) , false)
(bonk, (std::string), "default value")
)
)
{
if (baz && (bar > 1.0)) return foo;
return bonk.size();
}
int main()
{
function_with_named_parameters(1, 10.0);
function_with_named_parameters(7, _bar = 3.14);
function_with_named_parameters( _bar = 0.0, _foo = 42);
function_with_named_parameters( _bar = 2.5, _bonk= "Hello", _foo = 9);
function_with_named_parameters(9, 2.5, true, "Hello");
}
Trong một lưu ý cuối cùng, tôi sẽ không sử dụng thư viện kwargs này đơn giản vì có một số lựa chọn thay thế đủ tốt trong C ++ để đạt được điều tương tự. Cá nhân tôi sẽ chọn 1. hoặc 2. từ danh sách (không đầy đủ) ở trên.