Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
DeepSpeech
提交
fb1300f9
D
DeepSpeech
项目概览
PaddlePaddle
/
DeepSpeech
大约 2 年 前同步成功
通知
210
Star
8425
Fork
1598
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
245
列表
看板
标记
里程碑
合并请求
3
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
DeepSpeech
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
245
Issue
245
列表
看板
标记
里程碑
合并请求
3
合并请求
3
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
fb1300f9
编写于
6月 28, 2022
作者:
H
Hui Zhang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
format
上级
532aeb8d
变更
32
显示空白变更内容
内联
并排
Showing
32 changed file
with
2077 addition
and
1967 deletion
+2077
-1967
.pre-commit-config.yaml
.pre-commit-config.yaml
+2
-2
audio/audio/csrc/pybind/pybind.cpp
audio/audio/csrc/pybind/pybind.cpp
+6
-4
audio/audio/csrc/pybind/sox/io.cpp
audio/audio/csrc/pybind/sox/io.cpp
+45
-42
audio/audio/csrc/pybind/sox/io.h
audio/audio/csrc/pybind/sox/io.h
+2
-2
audio/audio/csrc/pybind/sox/utils.cpp
audio/audio/csrc/pybind/sox/utils.cpp
+66
-65
audio/audio/csrc/pybind/sox/utils.h
audio/audio/csrc/pybind/sox/utils.h
+15
-15
paddlespeech/__init__.py
paddlespeech/__init__.py
+0
-2
paddlespeech/audio/README.md
paddlespeech/audio/README.md
+1
-1
paddlespeech/audio/__init__.py
paddlespeech/audio/__init__.py
+1
-1
paddlespeech/audio/_class.py
paddlespeech/audio/_class.py
+4
-1
paddlespeech/audio/_extension.py
paddlespeech/audio/_extension.py
+3
-2
paddlespeech/audio/_internal/module_utils.py
paddlespeech/audio/_internal/module_utils.py
+18
-12
paddlespeech/audio/_ops.py
paddlespeech/audio/_ops.py
+5
-4
paddlespeech/audio/src/optional/optional.hpp
paddlespeech/audio/src/optional/optional.hpp
+1451
-1333
paddlespeech/audio/src/pybind/kaldi_frontend/feature_common.h
...lespeech/audio/src/pybind/kaldi_frontend/feature_common.h
+6
-11
paddlespeech/audio/src/pybind/kaldi_frontend/feature_common_inl.h
...eech/audio/src/pybind/kaldi_frontend/feature_common_inl.h
+7
-8
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature.cc
...lespeech/audio/src/pybind/kaldi_frontend/kaldi_feature.cc
+71
-70
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature.h
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature.h
+32
-33
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.cc
.../audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.cc
+24
-22
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.h
...h/audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.h
+3
-7
paddlespeech/audio/src/pybind/pybind.cpp
paddlespeech/audio/src/pybind/pybind.cpp
+8
-6
paddlespeech/audio/src/pybind/sox/io.cpp
paddlespeech/audio/src/pybind/sox/io.cpp
+47
-44
paddlespeech/audio/src/pybind/sox/io.h
paddlespeech/audio/src/pybind/sox/io.h
+4
-4
paddlespeech/audio/src/pybind/sox/utils.cpp
paddlespeech/audio/src/pybind/sox/utils.cpp
+68
-67
paddlespeech/audio/src/pybind/sox/utils.h
paddlespeech/audio/src/pybind/sox/utils.h
+17
-17
paddlespeech/audio/src/sox/io.cpp
paddlespeech/audio/src/sox/io.cpp
+105
-112
paddlespeech/audio/src/sox/io.h
paddlespeech/audio/src/sox/io.h
+16
-19
paddlespeech/audio/src/utils.cpp
paddlespeech/audio/src/utils.cpp
+8
-8
setup.py
setup.py
+15
-42
speechx/examples/ds2_ol/onnx/local/onnx_infer_shape.py
speechx/examples/ds2_ol/onnx/local/onnx_infer_shape.py
+5
-0
tools/setup_helpers/__init__.py
tools/setup_helpers/__init__.py
+1
-1
tools/setup_helpers/extension.py
tools/setup_helpers/extension.py
+21
-10
未找到文件。
.pre-commit-config.yaml
浏览文件 @
fb1300f9
...
...
@@ -76,4 +76,4 @@ repos:
entry
:
bash .pre-commit-hooks/cpplint.hook
language
:
system
files
:
\.(c|cc|cxx|cpp|cu|h|hpp|hxx)$
exclude
:
(?=speechx/speechx/kaldi|speechx/patch|speechx/tools/fstbin|speechx/tools/lmbin).*(\.cpp|\.cc|\.h|\.py)$
\ No newline at end of file
exclude
:
(?=speechx/speechx/kaldi|speechx/patch|speechx/tools/fstbin|speechx/tools/lmbin|paddlespeech/audio/src/optional).*(\.cpp|\.cc|\.h|\.hpp)$
\ No newline at end of file
audio/audio/csrc/pybind/pybind.cpp
浏览文件 @
fb1300f9
#include "pybind/sox/io.h"
PYBIND11_MODULE
(
_paddleaudio
,
m
)
{
m
.
def
(
"get_info_file"
,
&
paddleaudio
::
sox_io
::
get_info_file
,
m
.
def
(
"get_info_file"
,
&
paddleaudio
::
sox_io
::
get_info_file
,
"Get metadata of audio file."
);
m
.
def
(
"get_info_fileobj"
,
&
paddleaudio
::
sox_io
::
get_info_fileobj
,
m
.
def
(
"get_info_fileobj"
,
&
paddleaudio
::
sox_io
::
get_info_fileobj
,
"Get metadata of audio in file object."
);
}
\ No newline at end of file
audio/audio/csrc/pybind/sox/io.cpp
浏览文件 @
fb1300f9
...
...
@@ -8,7 +8,8 @@ namespace sox_io {
auto
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
SoxFormat
sf
(
sox_open_read
(
path
.
data
(),
SoxFormat
sf
(
sox_open_read
(
path
.
data
(),
/*signal=*/
nullptr
,
/*encoding=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
...
...
@@ -38,7 +39,9 @@ auto get_info_fileobj(py::object fileobj, const std::string &format)
// If the file is shorter than 256, then libsox cannot read the header.
auto
buf_size
=
(
num_read
>
256
)
?
num_read
:
256
;
SoxFormat
sf
(
sox_open_mem_read
(
buf
,
buf_size
,
SoxFormat
sf
(
sox_open_mem_read
(
buf
,
buf_size
,
/*signal=*/
nullptr
,
/*encoding=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
...
...
audio/audio/csrc/pybind/sox/io.h
浏览文件 @
fb1300f9
audio/audio/csrc/pybind/sox/utils.cpp
浏览文件 @
fb1300f9
...
...
@@ -31,7 +31,8 @@ auto read_fileobj(py::object *fileobj, const uint64_t size, char *buffer)
}
if
(
chunk_len
>
request
)
{
std
::
ostringstream
message
;
message
<<
"Requested up to "
<<
request
<<
" bytes but, "
message
<<
"Requested up to "
<<
request
<<
" bytes but, "
<<
"received "
<<
chunk_len
<<
" bytes. "
<<
"The given object does not confirm to read protocol of file "
"object."
;
...
...
@@ -48,8 +49,8 @@ int64_t get_buffer_size() { return sox_get_globals()->bufsiz; }
void
validate_input_file
(
const
SoxFormat
&
sf
,
const
std
::
string
&
path
)
{
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
throw
std
::
runtime_error
(
"Error loading audio file: failed to open file "
+
path
);
throw
std
::
runtime_error
(
"Error loading audio file: failed to open file "
+
path
);
}
if
(
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
throw
std
::
runtime_error
(
"Error loading audio file: unknown encoding."
);
...
...
audio/audio/csrc/pybind/sox/utils.h
浏览文件 @
fb1300f9
...
...
@@ -22,7 +22,7 @@ struct SoxFormat {
void
close
();
private:
private:
sox_format_t
*
fd_
;
};
...
...
paddlespeech/__init__.py
浏览文件 @
fb1300f9
...
...
@@ -14,5 +14,3 @@
import
_locale
_locale
.
_getdefaultlocale
=
(
lambda
*
args
:
[
'en_US'
,
'utf8'
])
paddlespeech/audio/README.md
浏览文件 @
fb1300f9
paddlespeech/audio/__init__.py
浏览文件 @
fb1300f9
paddlespeech/audio/_class.py
浏览文件 @
fb1300f9
import
types
class
_ClassNamespace
(
types
.
ModuleType
):
def
__init__
(
self
,
name
):
super
(
_ClassNamespace
,
self
).
__init__
(
'paddlespeech.classes'
+
name
)
...
...
@@ -11,6 +12,7 @@ class _ClassNamespace(types.ModuleType):
raise
RuntimeError
(
f
'Class
{
self
.
name
}
.
{
attr
}
not registered!'
)
return
proxy
class
_Classes
(
types
.
ModuleType
):
__file__
=
'_classes.py'
...
...
@@ -43,5 +45,6 @@ class _Classes(types.ModuleType):
"""
paddlespeech
.
ops
.
load_library
(
path
)
# The classes "namespace"
classes
=
_Classes
()
paddlespeech/audio/_extension.py
浏览文件 @
fb1300f9
...
...
@@ -64,7 +64,8 @@ def _init_ffmpeg():
try
:
_load_lib
(
"libpaddlleaudio_ffmpeg"
)
except
OSError
as
err
:
raise
ImportError
(
"FFmpeg libraries are not found. Please install FFmpeg."
)
from
err
raise
ImportError
(
"FFmpeg libraries are not found. Please install FFmpeg."
)
from
err
import
paddllespeech
.
_paddlleaudio_ffmpeg
# noqa
...
...
paddlespeech/audio/_internal/module_utils.py
浏览文件 @
fb1300f9
...
...
@@ -3,6 +3,7 @@ import warnings
from
functools
import
wraps
from
typing
import
Optional
def
is_module_available
(
*
modules
:
str
)
->
bool
:
r
"""Returns if a top-level module with :attr:`name` exists *without**
importing it. This is generally safer than try-catch block around a
...
...
@@ -26,19 +27,21 @@ def requires_module(*modules: str):
return
func
else
:
req
=
f
"module:
{
missing
[
0
]
}
"
if
len
(
missing
)
==
1
else
f
"modules:
{
missing
}
"
req
=
f
"module:
{
missing
[
0
]
}
"
if
len
(
missing
)
==
1
else
f
"modules:
{
missing
}
"
def
decorator
(
func
):
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires
{
req
}
"
)
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires
{
req
}
"
)
return
wrapped
return
decorator
def
deprecated
(
direction
:
str
,
version
:
Optional
[
str
]
=
None
):
def
deprecated
(
direction
:
str
,
version
:
Optional
[
str
]
=
None
):
"""Decorator to add deprecation message
Args:
direction (str): Migration steps to be given to users.
...
...
@@ -51,8 +54,7 @@ def deprecated(direction: str, version: Optional[str] = None):
message
=
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
has been deprecated "
f
'and will be removed from
{
"future"
if
version
is
None
else
version
}
release. '
f
"
{
direction
}
"
)
f
"
{
direction
}
"
)
warnings
.
warn
(
message
,
stacklevel
=
2
)
return
func
(
*
args
,
**
kwargs
)
...
...
@@ -62,7 +64,7 @@ def deprecated(direction: str, version: Optional[str] = None):
def
is_kaldi_available
():
return
is_module_available
(
"paddlespeech
"
.
_paddleaudio
") and paddlespeech.ops.paddleaudio.is_kaldi_available(
)
return
is_module_available
(
"paddlespeech
.audio._paddleaudio"
)
def
requires_kaldi
():
...
...
@@ -76,7 +78,8 @@ def requires_kaldi():
def
decorator
(
func
):
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
raise RuntimeError(f"
{
func
.
__module__
}.{
func
.
__name__
}
requires
kaldi
")
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires kaldi"
)
return
wrapped
...
...
@@ -91,7 +94,8 @@ def _check_soundfile_importable():
return
True
except
Exception
:
warnings.warn("
Failed
to
import
soundfile.
'soundfile'
backend
is
not
available
.
")
warnings
.
warn
(
"Failed to import soundfile. 'soundfile' backend is not available."
)
return
False
...
...
@@ -113,7 +117,8 @@ def requires_soundfile():
def
decorator
(
func
):
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
raise RuntimeError(f"
{
func
.
__module__
}.{
func
.
__name__
}
requires
soundfile
")
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires soundfile"
)
return
wrapped
...
...
@@ -121,7 +126,7 @@ def requires_soundfile():
def
is_sox_available
():
return is_module_available("
paddlespeech
.
_paddleaudio
") and paddlespeech.ops.paddleaudio.is_sox_available(
)
return
is_module_available
(
"paddlespeech.
audio._paddleaudio"
)
def
requires_sox
():
...
...
@@ -135,7 +140,8 @@ def requires_sox():
def
decorator
(
func
):
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
raise RuntimeError(f"
{
func
.
__module__
}.{
func
.
__name__
}
requires
sox
")
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires sox"
)
return
wrapped
...
...
paddlespeech/audio/_ops.py
浏览文件 @
fb1300f9
import
contextlib
import
ctypes
import
sys
import
os
import
sys
import
types
# Query `hasattr` only once.
_SET_GLOBAL_FLAGS
=
hasattr
(
sys
,
'getdlopenflags'
)
and
hasattr
(
sys
,
'setdlopenflags'
)
_SET_GLOBAL_FLAGS
=
hasattr
(
sys
,
'getdlopenflags'
)
and
hasattr
(
sys
,
'setdlopenflags'
)
@
contextlib
.
contextmanager
...
...
paddlespeech/audio/src/optional/optional.hpp
浏览文件 @
fb1300f9
...
...
@@ -55,27 +55,30 @@
// GCC < 5 doesn't support some standard C++11 type traits
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
std::has_trivial_copy_constructor<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
std::has_trivial_copy_assign<T>::value
// This one will be different for GCC 5.7 if it's ever supported
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \
std::is_trivially_destructible<T>::value
// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks
// std::vector
// for non-copyable types
#elif (defined(__GNUC__) && __GNUC__ < 8 && \
!defined(__clang__))
#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
namespace
tl
{
namespace
detail
{
template
<
class
T
>
struct
is_trivially_copy_constructible
:
std
::
is_trivially_copy_constructible
<
T
>
{};
namespace
detail
{
template
<
class
T
>
struct
is_trivially_copy_constructible
:
std
::
is_trivially_copy_constructible
<
T
>
{};
#ifdef _GLIBCXX_VECTOR
template
<
class
T
,
class
A
>
struct
is_trivially_copy_constructible
<
std
::
vector
<
T
,
A
>>
:
std
::
is_trivially_copy_constructible
<
T
>
{};
template
<
class
T
,
class
A
>
struct
is_trivially_copy_constructible
<
std
::
vector
<
T
,
A
>>
:
std
::
is_trivially_copy_constructible
<
T
>
{};
#endif
}
}
}
#endif
...
...
@@ -83,13 +86,15 @@ namespace tl {
tl::detail::is_trivially_copy_constructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
std::is_trivially_copy_assignable<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \
std::is_trivially_destructible<T>::value
#else
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
std::is_trivially_copy_constructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
std::is_trivially_copy_assignable<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \
std::is_trivially_destructible<T>::value
#endif
#if __cplusplus > 201103L
...
...
@@ -118,24 +123,29 @@ struct in_place_t {
static
constexpr
in_place_t
in_place
{};
#endif
template
<
class
T
>
class
optional
;
template
<
class
T
>
class
optional
;
namespace
detail
{
#ifndef TL_TRAITS_MUTEX
#define TL_TRAITS_MUTEX
// C++14-style aliases for brevity
template
<
class
T
>
using
remove_const_t
=
typename
std
::
remove_const
<
T
>::
type
;
template
<
class
T
>
using
remove_const_t
=
typename
std
::
remove_const
<
T
>::
type
;
template
<
class
T
>
using
remove_reference_t
=
typename
std
::
remove_reference
<
T
>::
type
;
template
<
class
T
>
using
decay_t
=
typename
std
::
decay
<
T
>::
type
;
template
<
class
T
>
using
decay_t
=
typename
std
::
decay
<
T
>::
type
;
template
<
bool
E
,
class
T
=
void
>
using
enable_if_t
=
typename
std
::
enable_if
<
E
,
T
>::
type
;
template
<
bool
B
,
class
T
,
class
F
>
using
conditional_t
=
typename
std
::
conditional
<
B
,
T
,
F
>::
type
;
// std::conjunction from C++17
template
<
class
...
>
struct
conjunction
:
std
::
true_type
{};
template
<
class
B
>
struct
conjunction
<
B
>
:
B
{};
template
<
class
...
>
struct
conjunction
:
std
::
true_type
{};
template
<
class
B
>
struct
conjunction
<
B
>
:
B
{};
template
<
class
B
,
class
...
Bs
>
struct
conjunction
<
B
,
Bs
...
>
:
std
::
conditional
<
bool
(
B
::
value
),
conjunction
<
Bs
...
>
,
B
>::
type
{};
...
...
@@ -148,31 +158,43 @@ struct conjunction<B, Bs...>
// which results in a hard-error when using it in a noexcept expression
// in some cases. This is a check to workaround the common failing case.
#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
template
<
class
T
>
struct
is_pointer_to_non_const_member_func
:
std
::
false_type
{};
template
<
class
T
>
struct
is_pointer_to_non_const_member_func
:
std
::
false_type
{};
template
<
class
T
,
class
Ret
,
class
...
Args
>
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)
(
Args
...)
>
:
std
::
true_type
{};
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)(
Args
...)
>
:
std
::
true_type
{};
template
<
class
T
,
class
Ret
,
class
...
Args
>
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)
(
Args
...)
&>
:
std
::
true_type
{};
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)(
Args
...)
&>
:
std
::
true_type
{};
template
<
class
T
,
class
Ret
,
class
...
Args
>
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)
(
Args
...)
&&>
:
std
::
true_type
{};
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)(
Args
...)
&&>
:
std
::
true_type
{};
template
<
class
T
,
class
Ret
,
class
...
Args
>
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)
(
Args
...)
volatile
>
:
std
::
true_type
{};
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)(
Args
...)
volatile
>
:
std
::
true_type
{};
template
<
class
T
,
class
Ret
,
class
...
Args
>
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)
(
Args
...)
volatile
&>
:
std
::
true_type
{};
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)(
Args
...)
volatile
&>
:
std
::
true_type
{};
template
<
class
T
,
class
Ret
,
class
...
Args
>
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)
(
Args
...)
volatile
&&>
:
std
::
true_type
{};
struct
is_pointer_to_non_const_member_func
<
Ret
(
T
::*
)(
Args
...)
volatile
&&>
:
std
::
true_type
{};
template
<
class
T
>
struct
is_const_or_const_ref
:
std
::
false_type
{};
template
<
class
T
>
struct
is_const_or_const_ref
<
T
const
&>
:
std
::
true_type
{};
template
<
class
T
>
struct
is_const_or_const_ref
<
T
const
>
:
std
::
true_type
{};
template
<
class
T
>
struct
is_const_or_const_ref
:
std
::
false_type
{};
template
<
class
T
>
struct
is_const_or_const_ref
<
T
const
&>
:
std
::
true_type
{};
template
<
class
T
>
struct
is_const_or_const_ref
<
T
const
>
:
std
::
true_type
{};
#endif
// std::invoke from C++17
// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
template
<
typename
Fn
,
typename
...
Args
,
template
<
typename
Fn
,
typename
...
Args
,
#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
typename
=
enable_if_t
<!
(
is_pointer_to_non_const_member_func
<
Fn
>
::
value
&&
is_const_or_const_ref
<
Args
...
>::
value
)
>
,
typename
=
enable_if_t
<!
(
is_pointer_to_non_const_member_func
<
Fn
>
::
value
&&
is_const_or_const_ref
<
Args
...
>::
value
)
>
,
#endif
typename
=
enable_if_t
<
std
::
is_member_pointer
<
decay_t
<
Fn
>>::
value
>
,
int
=
0
>
...
...
@@ -182,7 +204,8 @@ constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
return
std
::
mem_fn
(
f
)(
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
Fn
,
typename
...
Args
,
template
<
typename
Fn
,
typename
...
Args
,
typename
=
enable_if_t
<!
std
::
is_member_pointer
<
decay_t
<
Fn
>
>::
value
>>
constexpr
auto
invoke
(
Fn
&&
f
,
Args
&&
...
args
)
noexcept
(
noexcept
(
std
::
forward
<
Fn
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...)))
...
...
@@ -191,13 +214,16 @@ constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
}
// std::invoke_result from C++17
template
<
class
F
,
class
,
class
...
Us
>
struct
invoke_result_impl
;
template
<
class
F
,
class
,
class
...
Us
>
struct
invoke_result_impl
;
template
<
class
F
,
class
...
Us
>
struct
invoke_result_impl
<
F
,
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>
(),
std
::
declval
<
Us
>
()...),
void
()),
F
,
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>
(),
std
::
declval
<
Us
>
()...),
void
()),
Us
...
>
{
using
type
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>
(),
std
::
declval
<
Us
>
()...));
using
type
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>
(),
std
::
declval
<
Us
>
()...));
};
template
<
class
F
,
class
...
Us
>
...
...
@@ -208,9 +234,11 @@ using invoke_result_t = typename invoke_result<F, Us...>::type;
#if defined(_MSC_VER) && _MSC_VER <= 1900
// TODO make a version which works with MSVC 2015
template
<
class
T
,
class
U
=
T
>
struct
is_swappable
:
std
::
true_type
{};
template
<
class
T
,
class
U
=
T
>
struct
is_swappable
:
std
::
true_type
{};
template
<
class
T
,
class
U
=
T
>
struct
is_nothrow_swappable
:
std
::
true_type
{};
template
<
class
T
,
class
U
=
T
>
struct
is_nothrow_swappable
:
std
::
true_type
{};
#else
// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
namespace
swap_adl_tests
{
...
...
@@ -218,18 +246,23 @@ namespace swap_adl_tests {
// signature)
struct
tag
{};
template
<
class
T
>
tag
swap
(
T
&
,
T
&
);
template
<
class
T
,
std
::
size_t
N
>
tag
swap
(
T
(
&
a
)[
N
],
T
(
&
b
)[
N
]);
template
<
class
T
>
tag
swap
(
T
&
,
T
&
);
template
<
class
T
,
std
::
size_t
N
>
tag
swap
(
T
(
&
a
)[
N
],
T
(
&
b
)[
N
]);
// helper functions to test if an unqualified swap is possible, and if it
// becomes std::swap
template
<
class
,
class
>
std
::
false_type
can_swap
(...)
noexcept
(
false
);
template
<
class
T
,
class
U
,
template
<
class
,
class
>
std
::
false_type
can_swap
(...)
noexcept
(
false
);
template
<
class
T
,
class
U
,
class
=
decltype
(
swap
(
std
::
declval
<
T
&
>(),
std
::
declval
<
U
&>
()))
>
std
::
true_type
can_swap
(
int
)
noexcept
(
noexcept
(
swap
(
std
::
declval
<
T
&>
(),
std
::
declval
<
U
&>
())));
template
<
class
,
class
>
std
::
false_type
uses_std
(...);
template
<
class
,
class
>
std
::
false_type
uses_std
(...);
template
<
class
T
,
class
U
>
std
::
is_same
<
decltype
(
swap
(
std
::
declval
<
T
&>
(),
std
::
declval
<
U
&>
())),
tag
>
uses_std
(
int
);
...
...
@@ -281,13 +314,20 @@ struct is_nothrow_swappable
#endif
// std::void_t from C++17
template
<
class
...
>
struct
voider
{
using
type
=
void
;
};
template
<
class
...
Ts
>
using
void_t
=
typename
voider
<
Ts
...
>::
type
;
template
<
class
...
>
struct
voider
{
using
type
=
void
;
};
template
<
class
...
Ts
>
using
void_t
=
typename
voider
<
Ts
...
>::
type
;
// Trait for checking if a type is a tl::optional
template
<
class
T
>
struct
is_optional_impl
:
std
::
false_type
{};
template
<
class
T
>
struct
is_optional_impl
<
optional
<
T
>>
:
std
::
true_type
{};
template
<
class
T
>
using
is_optional
=
is_optional_impl
<
decay_t
<
T
>>
;
template
<
class
T
>
struct
is_optional_impl
:
std
::
false_type
{};
template
<
class
T
>
struct
is_optional_impl
<
optional
<
T
>>
:
std
::
true_type
{};
template
<
class
T
>
using
is_optional
=
is_optional_impl
<
decay_t
<
T
>>
;
// Change void to tl::monostate
template
<
class
U
>
...
...
@@ -297,7 +337,8 @@ template <class F, class U, class = invoke_result_t<F, U>>
using
get_map_return
=
optional
<
fixup_void
<
invoke_result_t
<
F
,
U
>>>
;
// Check if invoking F for some Us returns void
template
<
class
F
,
class
=
void
,
class
...
U
>
struct
returns_void_impl
;
template
<
class
F
,
class
=
void
,
class
...
U
>
struct
returns_void_impl
;
template
<
class
F
,
class
...
U
>
struct
returns_void_impl
<
F
,
void_t
<
invoke_result_t
<
F
,
U
...
>>
,
U
...
>
:
std
::
is_void
<
invoke_result_t
<
F
,
U
...
>>
{};
...
...
@@ -358,7 +399,8 @@ using enable_assign_from_other = detail::enable_if_t<
template
<
class
T
,
bool
=
::
std
::
is_trivially_destructible
<
T
>
::
value
>
struct
optional_storage_base
{
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
()
noexcept
:
m_dummy
(),
m_has_value
(
false
)
{}
:
m_dummy
(),
m_has_value
(
false
)
{}
template
<
class
...
U
>
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
(
in_place_t
,
U
&&
...
u
)
...
...
@@ -381,9 +423,11 @@ struct optional_storage_base {
};
// This case is for when T is trivially destructible.
template
<
class
T
>
struct
optional_storage_base
<
T
,
true
>
{
template
<
class
T
>
struct
optional_storage_base
<
T
,
true
>
{
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
()
noexcept
:
m_dummy
(),
m_has_value
(
false
)
{}
:
m_dummy
(),
m_has_value
(
false
)
{}
template
<
class
...
U
>
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
(
in_place_t
,
U
&&
...
u
)
...
...
@@ -402,7 +446,8 @@ template <class T> struct optional_storage_base<T, true> {
// This base class provides some handy member functions which can be used in
// further derived classes
template
<
class
T
>
struct
optional_operations_base
:
optional_storage_base
<
T
>
{
template
<
class
T
>
struct
optional_operations_base
:
optional_storage_base
<
T
>
{
using
optional_storage_base
<
T
>::
optional_storage_base
;
void
hard_reset
()
noexcept
{
...
...
@@ -410,12 +455,14 @@ template <class T> struct optional_operations_base : optional_storage_base<T> {
this
->
m_has_value
=
false
;
}
template
<
class
...
Args
>
void
construct
(
Args
&&
...
args
)
noexcept
{
template
<
class
...
Args
>
void
construct
(
Args
&&
...
args
)
noexcept
{
new
(
std
::
addressof
(
this
->
m_value
))
T
(
std
::
forward
<
Args
>
(
args
)...);
this
->
m_has_value
=
true
;
}
template
<
class
Opt
>
void
assign
(
Opt
&&
rhs
)
{
template
<
class
Opt
>
void
assign
(
Opt
&&
rhs
)
{
if
(
this
->
has_value
())
{
if
(
rhs
.
has_value
())
{
this
->
m_value
=
std
::
forward
<
Opt
>
(
rhs
).
get
();
...
...
@@ -478,9 +525,11 @@ struct optional_move_base : optional_copy_base<T> {
using
optional_copy_base
<
T
>::
optional_copy_base
;
};
#else
template
<
class
T
,
bool
=
false
>
struct
optional_move_base
;
template
<
class
T
,
bool
=
false
>
struct
optional_move_base
;
#endif
template
<
class
T
>
struct
optional_move_base
<
T
,
false
>
:
optional_copy_base
<
T
>
{
template
<
class
T
>
struct
optional_move_base
<
T
,
false
>
:
optional_copy_base
<
T
>
{
using
optional_copy_base
<
T
>::
optional_copy_base
;
optional_move_base
()
=
default
;
...
...
@@ -499,7 +548,8 @@ template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
};
// This class manages conditionally having a trivial copy assignment operator
template
<
class
T
,
bool
=
TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE
(
T
)
&&
template
<
class
T
,
bool
=
TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE
(
T
)
&&
TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE
(
T
)
&&
TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE
(
T
)>
struct
optional_copy_assign_base
:
optional_move_base
<
T
>
{
...
...
@@ -518,8 +568,8 @@ struct optional_copy_assign_base<T, false> : optional_move_base<T> {
this
->
assign
(
rhs
);
return
*
this
;
}
optional_copy_assign_base
&
operator
=
(
optional_copy_assign_base
&&
rhs
)
=
default
;
optional_copy_assign_base
&
operator
=
(
optional_copy_assign_base
&&
rhs
)
=
default
;
};
// This class manages conditionally having a trivial move assignment operator
...
...
@@ -528,14 +578,16 @@ struct optional_copy_assign_base<T, false> : optional_move_base<T> {
// to make do with a non-trivial move assignment operator even if T is trivially
// move assignable
#ifndef TL_OPTIONAL_GCC49
template
<
class
T
,
bool
=
std
::
is_trivially_destructible
<
T
>
::
value
template
<
class
T
,
bool
=
std
::
is_trivially_destructible
<
T
>
::
value
&&
std
::
is_trivially_move_constructible
<
T
>::
value
&&
std
::
is_trivially_move_assignable
<
T
>::
value
>
struct
optional_move_assign_base
:
optional_copy_assign_base
<
T
>
{
using
optional_copy_assign_base
<
T
>::
optional_copy_assign_base
;
};
#else
template
<
class
T
,
bool
=
false
>
struct
optional_move_assign_base
;
template
<
class
T
,
bool
=
false
>
struct
optional_move_assign_base
;
#endif
template
<
class
T
>
...
...
@@ -547,8 +599,8 @@ struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
optional_move_assign_base
(
optional_move_assign_base
&&
rhs
)
=
default
;
optional_move_assign_base
&
operator
=
(
const
optional_move_assign_base
&
rhs
)
=
default
;
optional_move_assign_base
&
operator
=
(
const
optional_move_assign_base
&
rhs
)
=
default
;
optional_move_assign_base
&
operator
=
(
optional_move_assign_base
&&
rhs
)
noexcept
(
...
...
@@ -561,46 +613,50 @@ struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
// optional_delete_ctor_base will conditionally delete copy and move
// constructors depending on whether T is copy/move constructible
template
<
class
T
,
bool
EnableCopy
=
std
::
is_copy_constructible
<
T
>
::
value
,
template
<
class
T
,
bool
EnableCopy
=
std
::
is_copy_constructible
<
T
>
::
value
,
bool
EnableMove
=
std
::
is_move_constructible
<
T
>::
value
>
struct
optional_delete_ctor_base
{
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
};
template
<
class
T
>
struct
optional_delete_ctor_base
<
T
,
true
,
false
>
{
template
<
class
T
>
struct
optional_delete_ctor_base
<
T
,
true
,
false
>
{
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
delete
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
};
template
<
class
T
>
struct
optional_delete_ctor_base
<
T
,
false
,
true
>
{
template
<
class
T
>
struct
optional_delete_ctor_base
<
T
,
false
,
true
>
{
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
delete
;
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
};
template
<
class
T
>
struct
optional_delete_ctor_base
<
T
,
false
,
false
>
{
template
<
class
T
>
struct
optional_delete_ctor_base
<
T
,
false
,
false
>
{
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
delete
;
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
delete
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
};
// optional_delete_assign_base will conditionally delete copy and move
...
...
@@ -615,43 +671,46 @@ struct optional_delete_assign_base {
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
};
template
<
class
T
>
struct
optional_delete_assign_base
<
T
,
true
,
false
>
{
template
<
class
T
>
struct
optional_delete_assign_base
<
T
,
true
,
false
>
{
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
delete
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
delete
;
};
template
<
class
T
>
struct
optional_delete_assign_base
<
T
,
false
,
true
>
{
template
<
class
T
>
struct
optional_delete_assign_base
<
T
,
false
,
true
>
{
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
delete
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
delete
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
};
template
<
class
T
>
struct
optional_delete_assign_base
<
T
,
false
,
false
>
{
template
<
class
T
>
struct
optional_delete_assign_base
<
T
,
false
,
false
>
{
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
delete
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
delete
;
optional_delete_assign_base
&
operator
=
(
const
optional_delete_assign_base
&
)
=
delete
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
delete
;
};
}
// namespace detail
...
...
@@ -666,7 +725,7 @@ static constexpr nullopt_t nullopt{nullopt_t::do_not_use{},
nullopt_t
::
do_not_use
{}};
class
bad_optional_access
:
public
std
::
exception
{
public:
public:
bad_optional_access
()
=
default
;
const
char
*
what
()
const
noexcept
{
return
"Optional has no value"
;
}
};
...
...
@@ -688,7 +747,7 @@ class optional : private detail::optional_move_assign_base<T>,
static_assert
(
!
std
::
is_same
<
detail
::
decay_t
<
T
>
,
nullopt_t
>::
value
,
"instantiation of optional with nullopt_t is ill-formed"
);
public:
public:
// The different versions for C++14 and 11 are needed because deduced return
// types are not SFINAE-safe. This provides better support for things like
// generic lambdas. C.f.
...
...
@@ -697,7 +756,8 @@ public:
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation which returns an optional on the stored
/// object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
...
...
@@ -706,16 +766,19 @@ public:
:
result
(
nullopt
);
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
T
&&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
}
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
...
...
@@ -725,12 +788,14 @@ public:
}
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
}
#endif
...
...
@@ -748,12 +813,14 @@ public:
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
detail
::
invoke_result_t
<
F
,
T
&&>
and_then
(
F
&&
f
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
detail
::
invoke_result_t
<
F
,
T
&&>
and_then
(
F
&&
f
)
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
T
&&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
}
...
...
@@ -774,7 +841,8 @@ public:
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
}
#endif
...
...
@@ -783,33 +851,37 @@ public:
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&
{
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&&
{
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
...
...
@@ -834,49 +906,53 @@ public:
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&
{
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&&
{
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&
{
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&
{
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&&
{
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#endif
...
...
@@ -885,8 +961,7 @@ public:
/// Calls `f` if the optional is empty
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
if
(
has_value
())
return
*
this
;
if
(
has_value
())
return
*
this
;
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -899,8 +974,7 @@ public:
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
&&
{
if
(
has_value
())
return
std
::
move
(
*
this
);
if
(
has_value
())
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -913,8 +987,7 @@ public:
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&
{
if
(
has_value
())
return
*
this
;
if
(
has_value
())
return
*
this
;
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -928,8 +1001,7 @@ public:
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
if
(
has_value
())
return
std
::
move
(
*
this
);
if
(
has_value
())
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -942,24 +1014,30 @@ public:
#endif
/// Maps the stored value with `f` if there is one, otherwise returns `u`.
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&
{
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
std
::
forward
<
U
>
(
u
);
}
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
);
}
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&
{
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
std
::
forward
<
U
>
(
u
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
);
}
#endif
...
...
@@ -974,7 +1052,8 @@ public:
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
)();
}
...
...
@@ -987,7 +1066,8 @@ public:
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
)();
}
#endif
...
...
@@ -1065,16 +1145,19 @@ public:
/// Constructs the stored value in-place using the given arguments.
template
<
class
...
Args
>
constexpr
explicit
optional
(
detail
::
enable_if_t
<
std
::
is_constructible
<
T
,
Args
...
>::
value
,
in_place_t
>
,
detail
::
enable_if_t
<
std
::
is_constructible
<
T
,
Args
...
>::
value
,
in_place_t
>
,
Args
&&
...
args
)
:
base
(
in_place
,
std
::
forward
<
Args
>
(
args
)...)
{}
template
<
class
U
,
class
...
Args
>
TL_OPTIONAL_11_CONSTEXPR
explicit
optional
(
detail
::
enable_if_t
<
std
::
is_constructible
<
T
,
std
::
initializer_list
<
U
>
&
,
detail
::
enable_if_t
<
std
::
is_constructible
<
T
,
std
::
initializer_list
<
U
>
&
,
Args
&&
...
>::
value
,
in_place_t
>
,
std
::
initializer_list
<
U
>
il
,
Args
&&
...
args
)
{
std
::
initializer_list
<
U
>
il
,
Args
&&
...
args
)
{
this
->
construct
(
il
,
std
::
forward
<
Args
>
(
args
)...);
}
...
...
@@ -1092,16 +1175,18 @@ public:
constexpr
explicit
optional
(
U
&&
u
)
:
base
(
in_place
,
std
::
forward
<
U
>
(
u
))
{}
/// Converting copy constructor.
template
<
class
U
,
detail
::
enable_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
,
detail
::
enable_if_t
<
std
::
is_convertible
<
const
U
&
,
T
>::
value
>
*
=
nullptr
>
template
<
class
U
,
detail
::
enable_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
,
detail
::
enable_if_t
<
std
::
is_convertible
<
const
U
&
,
T
>::
value
>
*
=
nullptr
>
optional
(
const
optional
<
U
>
&
rhs
)
{
if
(
rhs
.
has_value
())
{
this
->
construct
(
*
rhs
);
}
}
template
<
class
U
,
detail
::
enable_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
,
template
<
class
U
,
detail
::
enable_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
,
detail
::
enable_if_t
<!
std
::
is_convertible
<
const
U
&
,
T
>::
value
>
*
=
nullptr
>
explicit
optional
(
const
optional
<
U
>
&
rhs
)
{
...
...
@@ -1112,7 +1197,8 @@ public:
/// Converting move constructor.
template
<
class
U
,
detail
::
enable_from_other
<
T
,
U
,
U
&&
>
*
=
nullptr
,
class
U
,
detail
::
enable_from_other
<
T
,
U
,
U
&&
>
*
=
nullptr
,
detail
::
enable_if_t
<
std
::
is_convertible
<
U
&&
,
T
>::
value
>
*
=
nullptr
>
optional
(
optional
<
U
>
&&
rhs
)
{
if
(
rhs
.
has_value
())
{
...
...
@@ -1121,7 +1207,8 @@ public:
}
template
<
class
U
,
detail
::
enable_from_other
<
T
,
U
,
U
&&
>
*
=
nullptr
,
class
U
,
detail
::
enable_from_other
<
T
,
U
,
U
&&
>
*
=
nullptr
,
detail
::
enable_if_t
<!
std
::
is_convertible
<
U
&&
,
T
>::
value
>
*
=
nullptr
>
explicit
optional
(
optional
<
U
>
&&
rhs
)
{
if
(
rhs
.
has_value
())
{
...
...
@@ -1215,7 +1302,8 @@ public:
/// Constructs the value in-place, destroying the current one if there is
/// one.
template
<
class
...
Args
>
T
&
emplace
(
Args
&&
...
args
)
{
template
<
class
...
Args
>
T
&
emplace
(
Args
&&
...
args
)
{
static_assert
(
std
::
is_constructible
<
T
,
Args
&&
...
>::
value
,
"T must be constructible with Args"
);
...
...
@@ -1240,8 +1328,8 @@ public:
/// If both have a value, the values are swapped.
/// If one has a value, it is moved to the other and the movee is left
/// valueless.
void
swap
(
optional
&
rhs
)
noexcept
(
std
::
is_nothrow_move_constructible
<
T
>::
value
void
swap
(
optional
&
rhs
)
noexcept
(
std
::
is_nothrow_move_constructible
<
T
>::
value
&&
detail
::
is_nothrow_swappable
<
T
>::
value
)
{
using
std
::
swap
;
if
(
has_value
())
{
...
...
@@ -1277,7 +1365,9 @@ public:
}
#ifndef TL_OPTIONAL_NO_CONSTRR
constexpr
const
T
&&
operator
*
()
const
&&
{
return
std
::
move
(
this
->
m_value
);
}
constexpr
const
T
&&
operator
*
()
const
&&
{
return
std
::
move
(
this
->
m_value
);
}
#endif
/// Returns whether or not the optional has a value
...
...
@@ -1287,40 +1377,39 @@ public:
return
this
->
m_has_value
;
}
/// Returns the contained value if there is one, otherwise throws bad_optional_access
/// Returns the contained value if there is one, otherwise throws
/// bad_optional_access
TL_OPTIONAL_11_CONSTEXPR
T
&
value
()
&
{
if
(
has_value
())
return
this
->
m_value
;
if
(
has_value
())
return
this
->
m_value
;
throw
bad_optional_access
();
}
TL_OPTIONAL_11_CONSTEXPR
const
T
&
value
()
const
&
{
if
(
has_value
())
return
this
->
m_value
;
if
(
has_value
())
return
this
->
m_value
;
throw
bad_optional_access
();
}
TL_OPTIONAL_11_CONSTEXPR
T
&&
value
()
&&
{
if
(
has_value
())
return
std
::
move
(
this
->
m_value
);
if
(
has_value
())
return
std
::
move
(
this
->
m_value
);
throw
bad_optional_access
();
}
#ifndef TL_OPTIONAL_NO_CONSTRR
TL_OPTIONAL_11_CONSTEXPR
const
T
&&
value
()
const
&&
{
if
(
has_value
())
return
std
::
move
(
this
->
m_value
);
if
(
has_value
())
return
std
::
move
(
this
->
m_value
);
throw
bad_optional_access
();
}
#endif
/// Returns the stored value if there is one, otherwise returns `u`
template
<
class
U
>
constexpr
T
value_or
(
U
&&
u
)
const
&
{
template
<
class
U
>
constexpr
T
value_or
(
U
&&
u
)
const
&
{
static_assert
(
std
::
is_copy_constructible
<
T
>::
value
&&
std
::
is_convertible
<
U
&&
,
T
>::
value
,
"T must be copy constructible and convertible from U"
);
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
U
>
(
u
));
}
template
<
class
U
>
TL_OPTIONAL_11_CONSTEXPR
T
value_or
(
U
&&
u
)
&&
{
template
<
class
U
>
TL_OPTIONAL_11_CONSTEXPR
T
value_or
(
U
&&
u
)
&&
{
static_assert
(
std
::
is_move_constructible
<
T
>::
value
&&
std
::
is_convertible
<
U
&&
,
T
>::
value
,
"T must be move constructible and convertible from U"
);
...
...
@@ -1482,10 +1571,12 @@ namespace detail {
struct
i_am_secret
{};
}
// namespace detail
template
<
class
T
=
detail
::
i_am_secret
,
class
U
,
template
<
class
T
=
detail
::
i_am_secret
,
class
U
,
class
Ret
=
detail
::
conditional_t
<
std
::
is_same
<
T
,
detail
::
i_am_secret
>
::
value
,
detail
::
decay_t
<
U
>
,
T
>>
detail
::
decay_t
<
U
>
,
T
>>
inline
constexpr
optional
<
Ret
>
make_optional
(
U
&&
v
)
{
return
optional
<
Ret
>
(
std
::
forward
<
U
>
(
v
));
}
...
...
@@ -1501,13 +1592,15 @@ inline constexpr optional<T> make_optional(std::initializer_list<U> il,
}
#if __cplusplus >= 201703L
template
<
class
T
>
optional
(
T
)
->
optional
<
T
>
;
template
<
class
T
>
optional
(
T
)
->
optional
<
T
>
;
#endif
/// \exclude
namespace
detail
{
#ifdef TL_OPTIONAL_CXX14
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<!
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
...
...
@@ -1517,7 +1610,8 @@ constexpr auto optional_map_impl(Opt &&opt, F &&f) {
:
optional
<
Ret
>
(
nullopt
);
}
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
...
...
@@ -1530,7 +1624,8 @@ auto optional_map_impl(Opt &&opt, F &&f) {
return
optional
<
monostate
>
(
nullopt
);
}
#else
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<!
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
...
...
@@ -1541,7 +1636,8 @@ constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {
:
optional
<
Ret
>
(
nullopt
);
}
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
...
...
@@ -1559,8 +1655,9 @@ auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {
/// Specialization for when `T` is a reference. `optional<T&>` acts similarly
/// to a `T*`, but provides more operations and shows intent more clearly.
template
<
class
T
>
class
optional
<
T
&>
{
public:
template
<
class
T
>
class
optional
<
T
&>
{
public:
// The different versions for C++14 and 11 are needed because deduced return
// types are not SFINAE-safe. This provides better support for things like
// generic lambdas. C.f.
...
...
@@ -1570,7 +1667,8 @@ public:
/// Carries out some operation which returns an optional on the stored
/// object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
...
...
@@ -1579,7 +1677,8 @@ public:
:
result
(
nullopt
);
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
...
...
@@ -1588,7 +1687,8 @@ public:
:
result
(
nullopt
);
}
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
...
...
@@ -1598,7 +1698,8 @@ public:
}
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
...
...
@@ -1621,7 +1722,8 @@ public:
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
detail
::
invoke_result_t
<
F
,
T
&>
and_then
(
F
&&
f
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
detail
::
invoke_result_t
<
F
,
T
&>
and_then
(
F
&&
f
)
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
...
...
@@ -1656,48 +1758,52 @@ public:
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
map
(
F
&&
f
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&
{
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&&
{
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
const
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
...
...
@@ -1707,51 +1813,55 @@ public:
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&&
{
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
transform
(
F
&&
f
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&
{
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&&
{
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&
{
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
/// \group map
/// \synopsis template <class F> auto transform(F &&f) &&;
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&
{
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&&
{
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#endif
...
...
@@ -1760,8 +1870,7 @@ public:
/// Calls `f` if the optional is empty
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
if
(
has_value
())
return
*
this
;
if
(
has_value
())
return
*
this
;
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -1774,8 +1883,7 @@ public:
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
&&
{
if
(
has_value
())
return
std
::
move
(
*
this
);
if
(
has_value
())
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -1788,8 +1896,7 @@ public:
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&
{
if
(
has_value
())
return
*
this
;
if
(
has_value
())
return
*
this
;
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -1803,8 +1910,7 @@ public:
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
if
(
has_value
())
return
std
::
move
(
*
this
);
if
(
has_value
())
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
...
...
@@ -1817,24 +1923,30 @@ public:
#endif
/// Maps the stored value with `f` if there is one, otherwise returns `u`
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&
{
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
std
::
forward
<
U
>
(
u
);
}
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
);
}
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&
{
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
std
::
forward
<
U
>
(
u
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
);
}
#endif
...
...
@@ -1849,7 +1961,8 @@ public:
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
)();
}
...
...
@@ -1862,7 +1975,8 @@ public:
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
)();
}
#endif
...
...
@@ -1939,14 +2053,16 @@ public:
/// Constructs the stored value with `u`.
template
<
class
U
=
T
,
detail
::
enable_if_t
<!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<
!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
constexpr
optional
(
U
&&
u
)
noexcept
:
m_value
(
std
::
addressof
(
u
))
{
static_assert
(
std
::
is_lvalue_reference
<
U
>::
value
,
"U must be an lvalue"
);
static_assert
(
std
::
is_lvalue_reference
<
U
>::
value
,
"U must be an lvalue"
);
}
template
<
class
U
>
constexpr
explicit
optional
(
const
optional
<
U
>
&
rhs
)
noexcept
:
optional
(
*
rhs
)
{}
constexpr
explicit
optional
(
const
optional
<
U
>
&
rhs
)
noexcept
:
optional
(
*
rhs
)
{}
/// No-op
~
optional
()
=
default
;
...
...
@@ -1967,10 +2083,11 @@ public:
/// Rebinds this optional to `u`.
template
<
class
U
=
T
,
detail
::
enable_if_t
<!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<
!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
optional
&
operator
=
(
U
&&
u
)
{
static_assert
(
std
::
is_lvalue_reference
<
U
>::
value
,
"U must be an lvalue"
);
static_assert
(
std
::
is_lvalue_reference
<
U
>::
value
,
"U must be an lvalue"
);
m_value
=
std
::
addressof
(
u
);
return
*
this
;
}
...
...
@@ -1979,15 +2096,16 @@ public:
///
/// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
/// resets the stored value in `*this`.
template
<
class
U
>
optional
&
operator
=
(
const
optional
<
U
>
&
rhs
)
noexcept
{
template
<
class
U
>
optional
&
operator
=
(
const
optional
<
U
>
&
rhs
)
noexcept
{
m_value
=
std
::
addressof
(
rhs
.
value
());
return
*
this
;
}
/// Rebinds this optional to `u`.
template
<
class
U
=
T
,
detail
::
enable_if_t
<!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<
!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
optional
&
emplace
(
U
&&
u
)
noexcept
{
return
*
this
=
std
::
forward
<
U
>
(
u
);
}
...
...
@@ -2010,20 +2128,20 @@ public:
return
m_value
!=
nullptr
;
}
/// Returns the contained value if there is one, otherwise throws bad_optional_access
/// Returns the contained value if there is one, otherwise throws
/// bad_optional_access
TL_OPTIONAL_11_CONSTEXPR
T
&
value
()
{
if
(
has_value
())
return
*
m_value
;
if
(
has_value
())
return
*
m_value
;
throw
bad_optional_access
();
}
TL_OPTIONAL_11_CONSTEXPR
const
T
&
value
()
const
{
if
(
has_value
())
return
*
m_value
;
if
(
has_value
())
return
*
m_value
;
throw
bad_optional_access
();
}
/// Returns the stored value if there is one, otherwise returns `u`
template
<
class
U
>
constexpr
T
value_or
(
U
&&
u
)
const
&
noexcept
{
template
<
class
U
>
constexpr
T
value_or
(
U
&&
u
)
const
&
noexcept
{
static_assert
(
std
::
is_copy_constructible
<
T
>::
value
&&
std
::
is_convertible
<
U
&&
,
T
>::
value
,
"T must be copy constructible and convertible from U"
);
...
...
@@ -2031,7 +2149,8 @@ public:
}
/// \group value_or
template
<
class
U
>
TL_OPTIONAL_11_CONSTEXPR
T
value_or
(
U
&&
u
)
&&
noexcept
{
template
<
class
U
>
TL_OPTIONAL_11_CONSTEXPR
T
value_or
(
U
&&
u
)
&&
noexcept
{
static_assert
(
std
::
is_move_constructible
<
T
>::
value
&&
std
::
is_convertible
<
U
&&
,
T
>::
value
,
"T must be move constructible and convertible from U"
);
...
...
@@ -2041,20 +2160,19 @@ public:
/// Destroys the stored value if one exists, making the optional empty
void
reset
()
noexcept
{
m_value
=
nullptr
;
}
private:
private:
T
*
m_value
;
};
// namespace tl
}
// namespace tl
namespace
std
{
// TODO SFINAE
template
<
class
T
>
struct
hash
<
tl
::
optional
<
T
>>
{
template
<
class
T
>
struct
hash
<
tl
::
optional
<
T
>>
{
::
std
::
size_t
operator
()(
const
tl
::
optional
<
T
>
&
o
)
const
{
if
(
!
o
.
has_value
())
return
0
;
if
(
!
o
.
has_value
())
return
0
;
return
std
::
hash
<
tl
::
detail
::
remove_const_t
<
T
>>
()(
*
o
);
}
...
...
paddlespeech/audio/src/pybind/kaldi_frontend/feature_common.h
浏览文件 @
fb1300f9
...
...
@@ -14,9 +14,9 @@
#pragma once
#include "feat/feature-window.h"
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include "feat/feature-window.h"
namespace
paddleaudio
{
...
...
@@ -29,13 +29,9 @@ class StreamingFeatureTpl {
StreamingFeatureTpl
(
const
Options
&
opts
);
bool
ComputeFeature
(
const
kaldi
::
VectorBase
<
kaldi
::
BaseFloat
>&
wav
,
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
);
void
Reset
()
{
remained_wav_
.
Resize
(
0
);
}
void
Reset
()
{
remained_wav_
.
Resize
(
0
);
}
int
Dim
()
{
return
computer_
.
Dim
();
}
int
Dim
()
{
return
computer_
.
Dim
();
}
private:
bool
Compute
(
const
kaldi
::
Vector
<
kaldi
::
BaseFloat
>&
waves
,
...
...
@@ -49,4 +45,3 @@ class StreamingFeatureTpl {
}
// namespace ppspeech
#include "feature_common_inl.h"
paddlespeech/audio/src/pybind/kaldi_frontend/feature_common_inl.h
浏览文件 @
fb1300f9
...
...
@@ -17,15 +17,14 @@
namespace
paddleaudio
{
template
<
class
F
>
StreamingFeatureTpl
<
F
>::
StreamingFeatureTpl
(
const
Options
&
opts
)
:
opts_
(
opts
),
computer_
(
opts
),
window_function_
(
opts
.
frame_opts
)
{
//window_function_(computer_.GetFrameOptions()) { the opt set to zero
StreamingFeatureTpl
<
F
>::
StreamingFeatureTpl
(
const
Options
&
opts
)
:
opts_
(
opts
),
computer_
(
opts
),
window_function_
(
opts
.
frame_opts
)
{
// window_function_(computer_.GetFrameOptions()) { the opt set to zero
}
template
<
class
F
>
bool
StreamingFeatureTpl
<
F
>::
ComputeFeature
(
const
kaldi
::
VectorBase
<
kaldi
::
BaseFloat
>&
wav
,
bool
StreamingFeatureTpl
<
F
>::
ComputeFeature
(
const
kaldi
::
VectorBase
<
kaldi
::
BaseFloat
>&
wav
,
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
)
{
// append remaned waves
kaldi
::
int32
wav_len
=
wav
.
Dim
();
...
...
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature.cc
浏览文件 @
fb1300f9
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include "kaldi_feature_wrapper.h"
namespace
py
=
pybind11
;
namespace
py
=
pybind11
;
bool
InitFbank
(
float
samp_freq
,
// frame opts
bool
InitFbank
(
float
samp_freq
,
// frame opts
float
frame_shift_ms
,
float
frame_length_ms
,
float
dither
,
...
...
@@ -139,5 +138,7 @@ PYBIND11_MODULE(kaldi_featurepy, m) {
m
.
def
(
"InitFbank"
,
&
InitFbank
,
"init fbank"
);
m
.
def
(
"ResetFbank"
,
&
ResetFbank
,
"reset fbank"
);
m
.
def
(
"ComputeFbank"
,
&
ComputeFbank
,
"compute fbank"
);
m
.
def
(
"ComputeFbankStreaming"
,
&
ComputeFbankStreaming
,
"compute fbank streaming"
);
m
.
def
(
"ComputeFbankStreaming"
,
&
ComputeFbankStreaming
,
"compute fbank streaming"
);
}
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature.h
浏览文件 @
fb1300f9
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include "kaldi_feature_wrapper.h"
namespace
py
=
pybind11
;
namespace
py
=
pybind11
;
bool
InitFbank
(
float
samp_freq
,
// frame opts
bool
InitFbank
(
float
samp_freq
,
// frame opts
float
frame_shift_ms
,
float
frame_length_ms
,
float
dither
,
...
...
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.cc
浏览文件 @
fb1300f9
...
...
@@ -12,7 +12,8 @@ bool KaldiFeatureWrapper::InitFbank(kaldi::FbankOptions opts) {
return
true
;
}
py
::
array_t
<
double
>
KaldiFeatureWrapper
::
ComputeFbank
(
const
py
::
array_t
<
double
>
wav
)
{
py
::
array_t
<
double
>
KaldiFeatureWrapper
::
ComputeFbank
(
const
py
::
array_t
<
double
>
wav
)
{
py
::
buffer_info
info
=
wav
.
request
();
kaldi
::
Vector
<
kaldi
::
BaseFloat
>
input_wav
(
info
.
size
);
double
*
wav_ptr
=
(
double
*
)
info
.
ptr
;
...
...
@@ -38,8 +39,8 @@ py::array_t<double> KaldiFeatureWrapper::ComputeFbank(const py::array_t<double>
res_ptr
++
;
}
return
result
.
reshape
({
feats
.
Dim
()
/
Dim
(),
Dim
()});
/*
return
result
.
reshape
({
feats
.
Dim
()
/
Dim
(),
Dim
()});
/*
py::buffer_info info = wav.request();
std::cout << info.size << std::endl;
auto result = py::array_t<double>(info.size);
...
...
@@ -48,9 +49,10 @@ py::array_t<double> KaldiFeatureWrapper::ComputeFbank(const py::array_t<double>
py::buffer_info info_re = result.request();
memcpy(input_wav.Data(), (double*)info.ptr, wav.nbytes());
memcpy((double*)info_re.ptr, input_wav.Data(), input_wav.Dim()* sizeof(double));
memcpy((double*)info_re.ptr, input_wav.Data(), input_wav.Dim()*
sizeof(double));
return result;
*/
*/
}
...
...
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.h
浏览文件 @
fb1300f9
#include "base/kaldi-common.h"
#include "feature_common.h"
#include "feat/feature-fbank.h"
#include "feature_common.h"
#pragma once
...
...
@@ -14,12 +14,8 @@ class KaldiFeatureWrapper {
static
KaldiFeatureWrapper
*
GetInstance
();
bool
InitFbank
(
kaldi
::
FbankOptions
opts
);
py
::
array_t
<
double
>
ComputeFbank
(
const
py
::
array_t
<
double
>
wav
);
int
Dim
()
{
return
fbank_
->
Dim
();
}
void
ResetFbank
()
{
fbank_
->
Reset
();
}
int
Dim
()
{
return
fbank_
->
Dim
();
}
void
ResetFbank
()
{
fbank_
->
Reset
();
}
private:
std
::
unique_ptr
<
paddleaudio
::
Fbank
>
fbank_
;
...
...
paddlespeech/audio/src/pybind/pybind.cpp
浏览文件 @
fb1300f9
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
All rights reserved.
#include "paddlespeech/audio/src/pybind/sox/io.h"
PYBIND11_MODULE
(
_paddleaudio
,
m
)
{
m
.
def
(
"get_info_file"
,
&
paddleaudio
::
sox_io
::
get_info_file
,
m
.
def
(
"get_info_file"
,
&
paddleaudio
::
sox_io
::
get_info_file
,
"Get metadata of audio file."
);
m
.
def
(
"get_info_fileobj"
,
&
paddleaudio
::
sox_io
::
get_info_fileobj
,
m
.
def
(
"get_info_fileobj"
,
&
paddleaudio
::
sox_io
::
get_info_fileobj
,
"Get metadata of audio in file object."
);
}
\ No newline at end of file
paddlespeech/audio/src/pybind/sox/io.cpp
浏览文件 @
fb1300f9
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
All rights reserved.
#include "paddlespeech/audio/src/pybind/sox/io.h"
#include "paddlespeech/audio/src/pybind/sox/utils.h"
...
...
@@ -11,7 +11,8 @@ namespace sox_io {
auto
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
SoxFormat
sf
(
sox_open_read
(
path
.
data
(),
SoxFormat
sf
(
sox_open_read
(
path
.
data
(),
/*signal=*/
nullptr
,
/*encoding=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
...
...
@@ -41,7 +42,9 @@ auto get_info_fileobj(py::object fileobj, const std::string &format)
// If the file is shorter than 256, then libsox cannot read the header.
auto
buf_size
=
(
num_read
>
256
)
?
num_read
:
256
;
SoxFormat
sf
(
sox_open_mem_read
(
buf
,
buf_size
,
SoxFormat
sf
(
sox_open_mem_read
(
buf
,
buf_size
,
/*signal=*/
nullptr
,
/*encoding=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
...
...
paddlespeech/audio/src/pybind/sox/io.h
浏览文件 @
fb1300f9
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
All rights reserved.
#ifndef PADDLEAUDIO_PYBIND_SOX_IO_H
#define PADDLEAUDIO_PYBIND_SOX_IO_H
...
...
paddlespeech/audio/src/pybind/sox/utils.cpp
浏览文件 @
fb1300f9
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
All rights reserved.
#include "paddlespeech/audio/src/pybind/sox/utils.h"
...
...
@@ -34,7 +34,8 @@ auto read_fileobj(py::object *fileobj, const uint64_t size, char *buffer)
}
if
(
chunk_len
>
request
)
{
std
::
ostringstream
message
;
message
<<
"Requested up to "
<<
request
<<
" bytes but, "
message
<<
"Requested up to "
<<
request
<<
" bytes but, "
<<
"received "
<<
chunk_len
<<
" bytes. "
<<
"The given object does not confirm to read protocol of file "
"object."
;
...
...
@@ -51,8 +52,8 @@ int64_t get_buffer_size() { return sox_get_globals()->bufsiz; }
void
validate_input_file
(
const
SoxFormat
&
sf
,
const
std
::
string
&
path
)
{
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
throw
std
::
runtime_error
(
"Error loading audio file: failed to open file "
+
path
);
throw
std
::
runtime_error
(
"Error loading audio file: failed to open file "
+
path
);
}
if
(
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
throw
std
::
runtime_error
(
"Error loading audio file: unknown encoding."
);
...
...
paddlespeech/audio/src/pybind/sox/utils.h
浏览文件 @
fb1300f9
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
All rights reserved.
#ifndef PADDLEAUDIO_PYBIND_SOX_UTILS_H
#define PADDLEAUDIO_PYBIND_SOX_UTILS_H
...
...
@@ -25,7 +25,7 @@ struct SoxFormat {
void
close
();
private:
private:
sox_format_t
*
fd_
;
};
...
...
paddlespeech/audio/src/sox/io.cpp
浏览文件 @
fb1300f9
...
...
@@ -11,8 +11,7 @@ namespace paddleaudio {
namespace
sox_io
{
tl
::
optional
<
MetaDataTuple
>
get_info_file
(
const
std
::
string
&
path
,
const
tl
::
optional
<
std
::
string
>&
format
)
{
const
std
::
string
&
path
,
const
tl
::
optional
<
std
::
string
>&
format
)
{
SoxFormat
sf
(
sox_open_read
(
path
.
c_str
(),
/*signal=*/
nullptr
,
...
...
@@ -73,8 +72,7 @@ tl::optional<std::tuple<torch::Tensor, int64_t>> load_audio_file(
path
,
effects
,
normalize
,
channels_first
,
format
);
}
void
save_audio_file
(
const
std
::
string
&
path
,
void
save_audio_file
(
const
std
::
string
&
path
,
torch
::
Tensor
tensor
,
int64_t
sample_rate
,
bool
channels_first
,
...
...
@@ -85,25 +83,23 @@ void save_audio_file(
validate_input_tensor
(
tensor
);
const
auto
filetype
=
[
&
]()
{
if
(
format
.
has_value
())
return
format
.
value
();
if
(
format
.
has_value
())
return
format
.
value
();
return
get_filetype
(
path
);
}();
if
(
filetype
==
"amr-nb"
)
{
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
TORCH_CHECK
(
num_channels
==
1
,
"amr-nb format only supports single channel audio."
);
TORCH_CHECK
(
num_channels
==
1
,
"amr-nb format only supports single channel audio."
);
}
else
if
(
filetype
==
"htk"
)
{
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
TORCH_CHECK
(
num_channels
==
1
,
"htk format only supports single channel audio."
);
TORCH_CHECK
(
num_channels
==
1
,
"htk format only supports single channel audio."
);
}
else
if
(
filetype
==
"gsm"
)
{
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
TORCH_CHECK
(
num_channels
==
1
,
"gsm format only supports single channel audio."
);
TORCH_CHECK
(
sample_rate
==
8000
,
TORCH_CHECK
(
num_channels
==
1
,
"gsm format only supports single channel audio."
);
TORCH_CHECK
(
sample_rate
==
8000
,
"gsm format only supports a sampling rate of 8kHz."
);
}
const
auto
signal_info
=
...
...
@@ -111,8 +107,7 @@ void save_audio_file(
const
auto
encoding_info
=
get_encodinginfo_for_save
(
filetype
,
tensor
.
dtype
(),
compression
,
encoding
,
bits_per_sample
);
SoxFormat
sf
(
sox_open_write
(
path
.
c_str
(),
SoxFormat
sf
(
sox_open_write
(
path
.
c_str
(),
&
signal_info
,
&
encoding_info
,
/*filetype=*/
filetype
.
c_str
(),
...
...
@@ -134,11 +129,9 @@ void save_audio_file(
TORCH_LIBRARY_FRAGMENT
(
paddleaudio
,
m
)
{
m
.
def
(
"paddleaudio::sox_io_get_info"
,
&
paddleaudio
::
sox_io
::
get_info_file
);
m
.
def
(
"paddleaudio::sox_io_load_audio_file"
,
m
.
def
(
"paddleaudio::sox_io_load_audio_file"
,
&
paddleaudio
::
sox_io
::
load_audio_file
);
m
.
def
(
"paddleaudio::sox_io_save_audio_file"
,
m
.
def
(
"paddleaudio::sox_io_save_audio_file"
,
&
paddleaudio
::
sox_io
::
save_audio_file
);
}
...
...
paddlespeech/audio/src/sox/io.h
浏览文件 @
fb1300f9
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
All rights reserved.
#ifndef PADDLEAUDIO_SOX_IO_H
#define PADDLEAUDIO_SOX_IO_H
...
...
@@ -11,8 +11,7 @@
namespace
paddleaudio
{
namespace
sox_io
{
auto
get_effects
(
const
tl
::
optional
<
int64_t
>&
frame_offset
,
auto
get_effects
(
const
tl
::
optional
<
int64_t
>&
frame_offset
,
const
tl
::
optional
<
int64_t
>&
num_frames
)
->
std
::
vector
<
std
::
vector
<
std
::
string
>>
;
...
...
@@ -20,8 +19,7 @@ using MetaDataTuple =
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
tl
::
optional
<
MetaDataTuple
>
get_info_file
(
const
std
::
string
&
path
,
const
tl
::
optional
<
std
::
string
>&
format
);
const
std
::
string
&
path
,
const
tl
::
optional
<
std
::
string
>&
format
);
tl
::
optional
<
std
::
tuple
<
torch
::
Tensor
,
int64_t
>>
load_audio_file
(
const
std
::
string
&
path
,
...
...
@@ -31,8 +29,7 @@ tl::optional<std::tuple<torch::Tensor, int64_t>> load_audio_file(
tl
::
optional
<
bool
>
channels_first
,
const
tl
::
optional
<
std
::
string
>&
format
);
void
save_audio_file
(
const
std
::
string
&
path
,
void
save_audio_file
(
const
std
::
string
&
path
,
torch
::
Tensor
tensor
,
int64_t
sample_rate
,
bool
channels_first
,
...
...
paddlespeech/audio/src/utils.cpp
浏览文件 @
fb1300f9
setup.py
浏览文件 @
fb1300f9
...
...
@@ -18,9 +18,9 @@ import os
import
subprocess
as
sp
import
sys
from
pathlib
import
Path
from
typing
import
Union
from
typing
import
Tuple
from
typing
import
List
from
typing
import
Tuple
from
typing
import
Union
import
distutils.command.clean
from
setuptools
import
Command
...
...
@@ -38,43 +38,13 @@ VERSION = '0.0.0'
COMMITID
=
'none'
base
=
[
"editdistance"
,
"g2p_en"
,
"g2pM"
,
"h5py"
,
"inflect"
,
"jieba"
,
"jsonlines"
,
"kaldiio"
,
"librosa==0.8.1"
,
"loguru"
,
"matplotlib"
,
"nara_wpe"
,
"onnxruntime"
,
"pandas"
,
"paddlenlp"
,
"paddlespeech_feat"
,
"praatio==5.0.0"
,
"pypinyin"
,
"pypinyin-dict"
,
"python-dateutil"
,
"pyworld"
,
"resampy==0.2.2"
,
"sacrebleu"
,
"scipy"
,
"sentencepiece~=0.1.96"
,
"soundfile~=0.10"
,
"textgrid"
,
"timer"
,
"tqdm"
,
"typeguard"
,
"visualdl"
,
"webrtcvad"
,
"yacs~=0.1.8"
,
"prettytable"
,
"zhon"
,
'colorlog'
,
'pathos == 0.2.8'
"editdistance"
,
"g2p_en"
,
"g2pM"
,
"h5py"
,
"inflect"
,
"jieba"
,
"jsonlines"
,
"kaldiio"
,
"librosa==0.8.1"
,
"loguru"
,
"matplotlib"
,
"nara_wpe"
,
"onnxruntime"
,
"pandas"
,
"paddlenlp"
,
"paddlespeech_feat"
,
"praatio==5.0.0"
,
"pypinyin"
,
"pypinyin-dict"
,
"python-dateutil"
,
"pyworld"
,
"resampy==0.2.2"
,
"sacrebleu"
,
"scipy"
,
"sentencepiece~=0.1.96"
,
"soundfile~=0.10"
,
"textgrid"
,
"timer"
,
"tqdm"
,
"typeguard"
,
"visualdl"
,
"webrtcvad"
,
"yacs~=0.1.8"
,
"prettytable"
,
"zhon"
,
'colorlog'
,
'pathos == 0.2.8'
]
server
=
[
...
...
@@ -264,6 +234,7 @@ class clean(distutils.command.clean.clean):
print
(
f
"removing '
{
path
}
' (and everything under it)"
)
shutil
.
rmtree
(
str
(
path
),
ignore_errors
=
True
)
def
main
():
sha
=
check_output
([
"git"
,
"rev-parse"
,
"HEAD"
])
# commit id
branch
=
check_output
([
"git"
,
"rev-parse"
,
"--abbrev-ref"
,
"HEAD"
])
...
...
@@ -319,7 +290,8 @@ def main():
requirements
[
"develop"
],
'doc'
:
[
"sphinx"
,
"sphinx-rtd-theme"
,
"numpydoc"
,
"myst_parser"
,
"recommonmark>=0.5.0"
,
"sphinx-markdown-tables"
,
"sphinx-autobuild"
"recommonmark>=0.5.0"
,
"sphinx-markdown-tables"
,
"sphinx-autobuild"
],
'test'
:
[
'nose'
,
'torchaudio==0.10.2'
],
},
...
...
@@ -358,5 +330,6 @@ def main():
setup
(
**
setup_info
)
if
__name__
==
'__main__'
:
main
()
speechx/examples/ds2_ol/onnx/local/onnx_infer_shape.py
浏览文件 @
fb1300f9
...
...
@@ -494,6 +494,11 @@ class SymbolicShapeInference:
# contrib ops
'Attention'
,
'BiasGelu'
,
\
'EmbedLayerNormalization'
,
\
'FastGelu'
,
'Gelu'
,
'LayerNormalization'
,
\
...
...
tools/setup_helpers/__init__.py
浏览文件 @
fb1300f9
tools/setup_helpers/extension.py
浏览文件 @
fb1300f9
import
distutils.sysconfig
import
os
import
platform
import
subprocess
from
pathlib
import
Path
import
distutils.sysconfig
from
setuptools
import
Extension
from
setuptools.command.build_ext
import
build_ext
...
...
@@ -27,11 +27,13 @@ def _get_build(var, default=False):
if
val
in
trues
:
return
True
if
val
not
in
falses
:
print
(
f
"WARNING: Unexpected environment variable value `
{
var
}
=
{
val
}
`. "
f
"Expected one of
{
trues
+
falses
}
"
)
print
(
f
"WARNING: Unexpected environment variable value `
{
var
}
=
{
val
}
`. "
f
"Expected one of
{
trues
+
falses
}
"
)
return
False
_BUILD_SOX
=
False
if
platform
.
system
()
==
"Windows"
else
_get_build
(
"BUILD_SOX"
,
True
)
_BUILD_SOX
=
False
if
platform
.
system
()
==
"Windows"
else
_get_build
(
"BUILD_SOX"
,
True
)
_BUILD_MAD
=
_get_build
(
"BUILD_MAD"
,
False
)
# _BUILD_KALDI = False if platform.system() == "Windows" else _get_build("BUILD_KALDI", True)
# _BUILD_RNNT = _get_build("BUILD_RNNT", True)
...
...
@@ -40,7 +42,8 @@ _BUILD_MAD = _get_build("BUILD_MAD", False)
# _USE_ROCM = _get_build("USE_ROCM", torch.cuda.is_available() and torch.version.hip is not None)
# _USE_CUDA = _get_build("USE_CUDA", torch.cuda.is_available() and torch.version.hip is None)
# _USE_OPENMP = _get_build("USE_OPENMP", True) and "ATen parallel backend: OpenMP" in torch.__config__.parallel_info()
_PADDLESPEECH_CUDA_ARCH_LIST
=
os
.
environ
.
get
(
"PADDLESPEECH_CUDA_ARCH_LIST"
,
None
)
_PADDLESPEECH_CUDA_ARCH_LIST
=
os
.
environ
.
get
(
"PADDLESPEECH_CUDA_ARCH_LIST"
,
None
)
def
get_ext_modules
():
...
...
@@ -71,7 +74,8 @@ class CMakeBuild(build_ext):
if
ext
.
name
!=
"paddlespeech.audio._paddleaudio"
:
return
extdir
=
os
.
path
.
abspath
(
os
.
path
.
dirname
(
self
.
get_ext_filename
(
ext
.
name
)))
extdir
=
os
.
path
.
abspath
(
os
.
path
.
dirname
(
self
.
get_ext_filename
(
ext
.
name
)))
# required for auto-detection of auxiliary "native" libs
if
not
extdir
.
endswith
(
os
.
path
.
sep
):
...
...
@@ -101,8 +105,12 @@ class CMakeBuild(build_ext):
if
_PADDLESPEECH_CUDA_ARCH_LIST
is
not
None
:
# Convert MAJOR.MINOR[+PTX] list to new style one
# defined at https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html
_arches
=
_PADDLESPEECH_CUDA_ARCH_LIST
.
replace
(
"."
,
""
).
replace
(
" "
,
";"
).
split
(
";"
)
_arches
=
[
arch
[:
-
4
]
if
arch
.
endswith
(
"+PTX"
)
else
f
"
{
arch
}
-real"
for
arch
in
_arches
]
_arches
=
_PADDLESPEECH_CUDA_ARCH_LIST
.
replace
(
"."
,
""
).
replace
(
" "
,
";"
).
split
(
";"
)
_arches
=
[
arch
[:
-
4
]
if
arch
.
endswith
(
"+PTX"
)
else
f
"
{
arch
}
-real"
for
arch
in
_arches
]
cmake_args
+=
[
f
"-DCMAKE_CUDA_ARCHITECTURES=
{
';'
.
join
(
_arches
)
}
"
]
# Default to Ninja
...
...
@@ -131,10 +139,13 @@ class CMakeBuild(build_ext):
if
not
os
.
path
.
exists
(
self
.
build_temp
):
os
.
makedirs
(
self
.
build_temp
)
print
(
f
"cmake
{
_ROOT_DIR
}
{
' '
.
join
(
cmake_args
)
}
, cwd=
{
self
.
build_temp
}
"
)
subprocess
.
check_call
([
"cmake"
,
str
(
_ROOT_DIR
)]
+
cmake_args
,
cwd
=
self
.
build_temp
)
print
(
f
"cmake
{
_ROOT_DIR
}
{
' '
.
join
(
cmake_args
)
}
, cwd=
{
self
.
build_temp
}
"
)
subprocess
.
check_call
(
[
"cmake"
,
str
(
_ROOT_DIR
)]
+
cmake_args
,
cwd
=
self
.
build_temp
)
print
(
f
"cmake --build .
{
' '
.
join
(
build_args
)
}
, cwd=
{
self
.
build_temp
}
"
)
subprocess
.
check_call
([
"cmake"
,
"--build"
,
"."
]
+
build_args
,
cwd
=
self
.
build_temp
)
subprocess
.
check_call
(
[
"cmake"
,
"--build"
,
"."
]
+
build_args
,
cwd
=
self
.
build_temp
)
def
get_ext_filename
(
self
,
fullname
):
ext_filename
=
super
().
get_ext_filename
(
fullname
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录