cpp-kwargs 是一个能在 C++ 中实现类似于 Python **kwargs
传参的库。
它通过 C++ 强大的模板编程封装了一个 Kwargs
类以此来实现了该功能。
Python 中的 **kwargs
在 Python 中, **Kwargs
用于函数定义时接受任意数量的关键字参数。它将所有通过 Key=Value
形式传递的参数封装成一个字典,在函数内部可以通过 kwargs
访问这些参数,**kwargs
使得函数能够灵活地接受不定数量的关键字参数,提升了代码的可扩展性。官方文档。
-
Python (**kwargs) 和 cpp-kwargs 都支持的:
- 支持 按任意顺序排列的 键;
- 支持 缺少的 或 多余的 键;
- 支持 限定键名;
- 支持 任意类型的 值;
- 保留 原始值的类型信息;
-
cpp-kwargs 额外支持的:
- 自动的 类型转换(传入类型和传出的类型不一致时);
- 较小的开销,
Kwargs
的内部会尽可能地使用constexpr
,将在 编译期得到结果 (如果满足条件的话); - 键名不区别大小写(可选的);
Tip
推荐使用 C++ STL
更多的被声明为 constexpr
,代码的 编写 和 测试 皆在 C++
-
仅 Python (**kwargs) 支持的:
- 动态的返回值类型;
Tip
C++ 的返回值类型必须在编译时确定。
函数原型
-
In Python:
# 任意的键名 def func(**kwargs): ... # 限定键名(带默认值) def func(*, name='empty_name', old=0): ...
-
In C++:
// 任意的键名 auto func(Kwargs<> kwargs = {}) {...} // 限定键名(无需带默认值) auto func(Kwargs<"name"_opt, "old"_opt> kwargs = {}) {...}
外部调用
-
In Python:
# 正常 func(name='huanhuanonly', old=18) # 非预期的类型 func(name='huanhuanonly', old='18') # 相反的顺序 func(old=18, name='huanhuanonly') # 空的参数 func()
-
In C++:
// 正常 func({ {"name", "huanhuanonly"}, {"old", 18} }); // 非预期的类型 func({ {"name", "huanhuanonly"}, {"old", "18"} }); // 相反的顺序 func({ {"old", 18}, {"name", "huanhuanonly"} }); // 空的参数 func()
内部获取值
-
In Python:
str(kwargs['name']) if 'name' in kwargs else 'empty_name' int(kwargs['old']) if 'old' in kwargs else 0
-
In C++:
kwargs["name"].valueOr<std::string>("empty_name") kwargs["old"].valueOr<int>(0) // kwargs["name"].hasValue() // 等效于 // if 'name' in kwargs
struct Font
{
std::string faceName;
int size;
float escapement;
bool italic;
// Or Kwargs<> kwargs = {} without checking.
Font(Kwargs<
"faceName"_opt, /* Or */ "name"_opt,
"size"_opt,
"escapement"_opt,
"italic"_opt, /* Or */ "i"_opt> kwargs = {})
: faceName(kwargs["faceName"_opt or "name"].valueOr<std::string>())
, size(kwargs["size"].valueOr<int>(9))
, escapement(kwargs["escapement"].valueOr<float>(0.00f))
, italic(kwargs["italic"_opt or "i"].valueOr<bool>(false))
{ }
};
以下构造 Font
的方式都是有效的:
-
Font()
- 同等于:
Font{ std::string(), 9, 0.00f, false }
- 同等于:
-
Font({ })
- 同等于:
Font{ std::string(), 9, 0.00f, false }
- 同等于:
-
Font({ {"name", "Arial"}, {"italic", true} })
- 同等于:
Font{ std::string("Arial"), 9, 0.00f, true }
- 同等于:
-
Font({ {"italic", "true"}, {"name", "Arial"} })
- 同等于:
Font{ std::string("Arial"), 9, 0.00f, true }
- 同等于:
-
Font({ {"i", "True"}, {"faceName", "Arial"} })
- 同等于:
Font{ std::string("Arial"), 9, 0.00f, true }
- 同等于:
-
Font({ {"size", 18}, {"escapement", 45} })
- 同等于:
Font{ std::string(), 18, 45.00f, false }
- 同等于:
-
Font({ {"size", "18"}, {"escapement", "49.2"} })
- 同等于:
Font{ std::string(), 18, 49.20f, false }
- 同等于:
-
Font({ {"size", 18.8}, {"escapement", 49.2}, {"i", 't'} })
- 同等于:
Font{ std::string(), 18, 49.20f, true }
- 同等于:
-
In Python
def printList(value: list, /, *, sep = ', ', end = '\n'): if len(value) == 0: return for i in range(len(value) - 1): print(value[i], end=sep) print(value[-1], end=end)
-
In C++
void printList( const std::vector<int>& value, Kwargs<"sep"_opt, "end"_opt> kwargs = { }) { if (value.empty()) return; for (std::size_t i = 0; i < value.size() - 1; ++i) std::cout << value[i], std::cout << kwargs["sep"].valueOr<std::string_view>(", "); std::cout << value.back(); std::cout << kwargs["end"].valueOr<std::string_view>("\n"); }
调用:
-
In Python
printList([1, 4, 3, 3, 2, 2, 3], sep=' | ', end='.')
-
In C++
printList( {1, 4, 3, 3, 2, 2, 3}, { {"sep", " | "}, {"end", '.'} });
git clone https://github.com/huanhuanonly/cpp-kwargs.git
- CMakeList.txt
set (CPP_KWARGS_REPOS "https://github.com/huanhuanonly/cpp-kwargs.git")
set (CPP_KWARGS_PATH "${CMAKE_SOURCE_DIR}/cpp-kwargs")
include (FetchContent)
if (NOT EXISTS ${CPP_KWARGS_PATH})
FetchContent_Declare (
CppKwargs
GIT_REPOSITORY ${CPP_KWARGS_REPOS}
GIT_TAG main
GIT_SHALLOW TRUE
SOURCE_DIR ${CPP_KWARGS_PATH}
)
FetchContent_MakeAvailable (CppKwargs)
endif()
include_directories (${CPP_KWARGS_PATH})
- main.cpp
#include <CppKwargs.h>
Tip
该项目只需要一个头文件即可运行。
-
在
#include "CppKwargs.h"
前定义KWARGSKEY_CASE_INSENSITIVE
:#ifndef KWARGSKEY_CASE_INSENSITIVE # define KWARGSKEY_CASE_INSENSITIVE #endif #include "CppKwargs.h"
-
或者,在你的项目中的 CMakeList.txt 文件中添加以下行:
target_compile_definitions (YourExecutable PRIVATE KWARGSKEY_CASE_INSENSITIVE)
-
所有的整型和浮点型之间的互相转换。
-
对于所有枚举类型
enum
视为其底层类型(整型)。
Tip
即使 enum
的底层类型是 char
/ uchar
,它也会作为一个整型(std::int8_t
/ std::uint8_t
)。
-
std::string
$\longleftrightarrow$ std::string_view
。 -
std::string
/std::string_view
$\longleftrightarrow$ const char*
。 -
std::vector<char>
/std::array<char>
/std::string_view
$\longrightarrow$ const char*
(并不保证有\0
结束符)。 -
const char*
/std::string
/std::string_view
$\longrightarrow$ Integer
/Floating point
。 -
Integer
/Floating point
$\longrightarrow$ std::string
。 -
const char*
/std::string
/std::string_view
$\longleftrightarrow$ char
/uchar
(取首字符,空则返回\0
)。 -
bool
$\longrightarrow$ const char*
/std::string
/std::string_view
("true"
or"false"
)。 -
"true"
/"True"
/"TRUE"
/'t'
/'T'
$\longrightarrow$ true
。 -
"false"
/"False"
/"FALSE"
/'f'
/'F'
$\longrightarrow$ false
。 -
可迭代的容器(拥有
.begin()
、.end()
和 前向迭代器)$\longrightarrow$ 可插入的容器。
Note
两个容器必须都要包含 ::value_type
类型,值类型不需要一致,不一致时将按照以上规则进行转换。
可插入的容器
拥有以下成员函数之一(按顺序):.append()
.push_back()
.push()
.insert()
.push_front()
-
Copyright
$2024\text{-}2025$ Yang Huanhuan (3347484963@qq.com). All rights reserved. -
Created by Yang Huanhuan on
$December$ $29, 2024, 14:40:45$ . -
Goodbye
$2024$ , Hello$2025$ !