Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
DeepSpeech
提交
a3911ab5
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看板
未验证
提交
a3911ab5
编写于
6月 28, 2022
作者:
H
Hui Zhang
提交者:
GitHub
6月 28, 2022
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #2089 from zh794390558/cpplint
[audio] format code
上级
fb7cbb34
fb1300f9
变更
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
浏览文件 @
a3911ab5
...
@@ -5,7 +5,7 @@ repos:
...
@@ -5,7 +5,7 @@ repos:
-
id
:
yapf
-
id
:
yapf
files
:
\.py$
files
:
\.py$
exclude
:
(?=third_party).*(\.py)$
exclude
:
(?=third_party).*(\.py)$
-
repo
:
https://github.com/pre-commit/pre-commit-hooks
-
repo
:
https://github.com/pre-commit/pre-commit-hooks
rev
:
a11d9314b22d8f8c7556443875b731ef05965464
rev
:
a11d9314b22d8f8c7556443875b731ef05965464
hooks
:
hooks
:
...
@@ -76,4 +76,4 @@ repos:
...
@@ -76,4 +76,4 @@ repos:
entry
:
bash .pre-commit-hooks/cpplint.hook
entry
:
bash .pre-commit-hooks/cpplint.hook
language
:
system
language
:
system
files
:
\.(c|cc|cxx|cpp|cu|h|hpp|hxx)$
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)$
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
\ No newline at end of file
audio/audio/csrc/pybind/pybind.cpp
浏览文件 @
a3911ab5
#include "pybind/sox/io.h"
#include "pybind/sox/io.h"
PYBIND11_MODULE
(
_paddleaudio
,
m
)
{
PYBIND11_MODULE
(
_paddleaudio
,
m
)
{
m
.
def
(
"get_info_file"
,
&
paddleaudio
::
sox_io
::
get_info_file
,
m
.
def
(
"get_info_file"
,
"Get metadata of audio file."
);
&
paddleaudio
::
sox_io
::
get_info_file
,
m
.
def
(
"get_info_fileobj"
,
&
paddleaudio
::
sox_io
::
get_info_fileobj
,
"Get metadata of audio file."
);
"Get metadata of audio in file object."
);
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
浏览文件 @
a3911ab5
...
@@ -8,51 +8,54 @@ namespace sox_io {
...
@@ -8,51 +8,54 @@ namespace sox_io {
auto
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
format
)
auto
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
SoxFormat
sf
(
sox_open_read
(
path
.
data
(),
SoxFormat
sf
(
/*signal=*/
nullptr
,
sox_open_read
(
path
.
data
(),
/*encoding=*/
nullptr
,
/*signal=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
/*encoding=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
validate_input_file
(
sf
,
path
);
validate_input_file
(
sf
,
path
);
return
std
::
make_tuple
(
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
return
std
::
make_tuple
(
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
get_encoding
(
sf
->
encoding
.
encoding
));
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
get_encoding
(
sf
->
encoding
.
encoding
));
}
}
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
const
auto
capacity
=
[
&
]()
{
const
auto
capacity
=
[
&
]()
{
const
auto
bufsiz
=
get_buffer_size
();
const
auto
bufsiz
=
get_buffer_size
();
const
int64_t
kDefaultCapacityInBytes
=
4096
;
const
int64_t
kDefaultCapacityInBytes
=
4096
;
return
(
bufsiz
>
kDefaultCapacityInBytes
)
?
bufsiz
return
(
bufsiz
>
kDefaultCapacityInBytes
)
?
bufsiz
:
kDefaultCapacityInBytes
;
:
kDefaultCapacityInBytes
;
}();
}();
std
::
string
buffer
(
capacity
,
'\0'
);
std
::
string
buffer
(
capacity
,
'\0'
);
auto
*
buf
=
const_cast
<
char
*>
(
buffer
.
data
());
auto
*
buf
=
const_cast
<
char
*>
(
buffer
.
data
());
auto
num_read
=
read_fileobj
(
&
fileobj
,
capacity
,
buf
);
auto
num_read
=
read_fileobj
(
&
fileobj
,
capacity
,
buf
);
// If the file is shorter than 256, then libsox cannot read the header.
// If the file is shorter than 256, then libsox cannot read the header.
auto
buf_size
=
(
num_read
>
256
)
?
num_read
:
256
;
auto
buf_size
=
(
num_read
>
256
)
?
num_read
:
256
;
SoxFormat
sf
(
sox_open_mem_read
(
buf
,
buf_size
,
SoxFormat
sf
(
sox_open_mem_read
(
/*signal=*/
nullptr
,
buf
,
/*encoding=*/
nullptr
,
buf_size
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
/*signal=*/
nullptr
,
/*encoding=*/
nullptr
,
// In case of streamed data, length can be 0
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
validate_input_memfile
(
sf
);
// In case of streamed data, length can be 0
return
std
::
make_tuple
(
validate_input_memfile
(
sf
);
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
return
std
::
make_tuple
(
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
get_encoding
(
sf
->
encoding
.
encoding
));
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
get_encoding
(
sf
->
encoding
.
encoding
));
}
}
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_io
}
// namespace sox_io
audio/audio/csrc/pybind/sox/io.h
浏览文件 @
a3911ab5
...
@@ -12,7 +12,7 @@ auto get_info_file(const std::string &path, const std::string &format)
...
@@ -12,7 +12,7 @@ auto get_info_file(const std::string &path, const std::string &format)
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_io
}
// namespace sox_io
#endif
#endif
audio/audio/csrc/pybind/sox/utils.cpp
浏览文件 @
a3911ab5
...
@@ -12,86 +12,87 @@ sox_format_t *SoxFormat::operator->() const noexcept { return fd_; }
...
@@ -12,86 +12,87 @@ sox_format_t *SoxFormat::operator->() const noexcept { return fd_; }
SoxFormat
::
operator
sox_format_t
*
()
const
noexcept
{
return
fd_
;
}
SoxFormat
::
operator
sox_format_t
*
()
const
noexcept
{
return
fd_
;
}
void
SoxFormat
::
close
()
{
void
SoxFormat
::
close
()
{
if
(
fd_
!=
nullptr
)
{
if
(
fd_
!=
nullptr
)
{
sox_close
(
fd_
);
sox_close
(
fd_
);
fd_
=
nullptr
;
fd_
=
nullptr
;
}
}
}
}
auto
read_fileobj
(
py
::
object
*
fileobj
,
const
uint64_t
size
,
char
*
buffer
)
auto
read_fileobj
(
py
::
object
*
fileobj
,
const
uint64_t
size
,
char
*
buffer
)
->
uint64_t
{
->
uint64_t
{
uint64_t
num_read
=
0
;
uint64_t
num_read
=
0
;
while
(
num_read
<
size
)
{
while
(
num_read
<
size
)
{
auto
request
=
size
-
num_read
;
auto
request
=
size
-
num_read
;
auto
chunk
=
static_cast
<
std
::
string
>
(
auto
chunk
=
static_cast
<
std
::
string
>
(
static_cast
<
py
::
bytes
>
(
fileobj
->
attr
(
"read"
)(
request
)));
static_cast
<
py
::
bytes
>
(
fileobj
->
attr
(
"read"
)(
request
)));
auto
chunk_len
=
chunk
.
length
();
auto
chunk_len
=
chunk
.
length
();
if
(
chunk_len
==
0
)
{
if
(
chunk_len
==
0
)
{
break
;
break
;
}
}
if
(
chunk_len
>
request
)
{
if
(
chunk_len
>
request
)
{
std
::
ostringstream
message
;
std
::
ostringstream
message
;
message
<<
"Requested up to "
<<
request
<<
" bytes but, "
message
<<
"received "
<<
chunk_len
<<
" bytes. "
<<
"Requested up to "
<<
request
<<
" bytes but, "
<<
"The given object does not confirm to read protocol of file "
<<
"received "
<<
chunk_len
<<
" bytes. "
"object."
;
<<
"The given object does not confirm to read protocol of file "
throw
std
::
runtime_error
(
message
.
str
());
"object."
;
throw
std
::
runtime_error
(
message
.
str
());
}
memcpy
(
buffer
,
chunk
.
data
(),
chunk_len
);
buffer
+=
chunk_len
;
num_read
+=
chunk_len
;
}
}
memcpy
(
buffer
,
chunk
.
data
(),
chunk_len
);
return
num_read
;
buffer
+=
chunk_len
;
num_read
+=
chunk_len
;
}
return
num_read
;
}
}
int64_t
get_buffer_size
()
{
return
sox_get_globals
()
->
bufsiz
;
}
int64_t
get_buffer_size
()
{
return
sox_get_globals
()
->
bufsiz
;
}
void
validate_input_file
(
const
SoxFormat
&
sf
,
const
std
::
string
&
path
)
{
void
validate_input_file
(
const
SoxFormat
&
sf
,
const
std
::
string
&
path
)
{
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
throw
std
::
runtime_error
(
"Error loading audio file: failed to open file "
+
throw
std
::
runtime_error
(
path
);
"Error loading audio file: failed to open file "
+
path
);
}
}
if
(
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
if
(
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
throw
std
::
runtime_error
(
"Error loading audio file: unknown encoding."
);
throw
std
::
runtime_error
(
"Error loading audio file: unknown encoding."
);
}
}
}
}
void
validate_input_memfile
(
const
SoxFormat
&
sf
)
{
void
validate_input_memfile
(
const
SoxFormat
&
sf
)
{
return
validate_input_file
(
sf
,
"<in memory buffer>"
);
return
validate_input_file
(
sf
,
"<in memory buffer>"
);
}
}
std
::
string
get_encoding
(
sox_encoding_t
encoding
)
{
std
::
string
get_encoding
(
sox_encoding_t
encoding
)
{
switch
(
encoding
)
{
switch
(
encoding
)
{
case
SOX_ENCODING_UNKNOWN
:
case
SOX_ENCODING_UNKNOWN
:
return
"UNKNOWN"
;
return
"UNKNOWN"
;
case
SOX_ENCODING_SIGN2
:
case
SOX_ENCODING_SIGN2
:
return
"PCM_S"
;
return
"PCM_S"
;
case
SOX_ENCODING_UNSIGNED
:
case
SOX_ENCODING_UNSIGNED
:
return
"PCM_U"
;
return
"PCM_U"
;
case
SOX_ENCODING_FLOAT
:
case
SOX_ENCODING_FLOAT
:
return
"PCM_F"
;
return
"PCM_F"
;
case
SOX_ENCODING_FLAC
:
case
SOX_ENCODING_FLAC
:
return
"FLAC"
;
return
"FLAC"
;
case
SOX_ENCODING_ULAW
:
case
SOX_ENCODING_ULAW
:
return
"ULAW"
;
return
"ULAW"
;
case
SOX_ENCODING_ALAW
:
case
SOX_ENCODING_ALAW
:
return
"ALAW"
;
return
"ALAW"
;
case
SOX_ENCODING_MP3
:
case
SOX_ENCODING_MP3
:
return
"MP3"
;
return
"MP3"
;
case
SOX_ENCODING_VORBIS
:
case
SOX_ENCODING_VORBIS
:
return
"VORBIS"
;
return
"VORBIS"
;
case
SOX_ENCODING_AMR_WB
:
case
SOX_ENCODING_AMR_WB
:
return
"AMR_WB"
;
return
"AMR_WB"
;
case
SOX_ENCODING_AMR_NB
:
case
SOX_ENCODING_AMR_NB
:
return
"AMR_NB"
;
return
"AMR_NB"
;
case
SOX_ENCODING_OPUS
:
case
SOX_ENCODING_OPUS
:
return
"OPUS"
;
return
"OPUS"
;
case
SOX_ENCODING_GSM
:
case
SOX_ENCODING_GSM
:
return
"GSM"
;
return
"GSM"
;
default:
default:
return
"UNKNOWN"
;
return
"UNKNOWN"
;
}
}
}
}
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_utils
}
// namespace sox_utils
audio/audio/csrc/pybind/sox/utils.h
浏览文件 @
a3911ab5
...
@@ -11,19 +11,19 @@ namespace sox_utils {
...
@@ -11,19 +11,19 @@ namespace sox_utils {
/// helper class to automatically close sox_format_t*
/// helper class to automatically close sox_format_t*
struct
SoxFormat
{
struct
SoxFormat
{
explicit
SoxFormat
(
sox_format_t
*
fd
)
noexcept
;
explicit
SoxFormat
(
sox_format_t
*
fd
)
noexcept
;
SoxFormat
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
(
SoxFormat
&&
other
)
=
delete
;
SoxFormat
(
SoxFormat
&&
other
)
=
delete
;
SoxFormat
&
operator
=
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
&
operator
=
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
&
operator
=
(
SoxFormat
&&
other
)
=
delete
;
SoxFormat
&
operator
=
(
SoxFormat
&&
other
)
=
delete
;
~
SoxFormat
();
~
SoxFormat
();
sox_format_t
*
operator
->
()
const
noexcept
;
sox_format_t
*
operator
->
()
const
noexcept
;
operator
sox_format_t
*
()
const
noexcept
;
operator
sox_format_t
*
()
const
noexcept
;
void
close
();
void
close
();
private:
private:
sox_format_t
*
fd_
;
sox_format_t
*
fd_
;
};
};
auto
read_fileobj
(
py
::
object
*
fileobj
,
uint64_t
size
,
char
*
buffer
)
->
uint64_t
;
auto
read_fileobj
(
py
::
object
*
fileobj
,
uint64_t
size
,
char
*
buffer
)
->
uint64_t
;
...
@@ -36,7 +36,7 @@ void validate_input_memfile(const SoxFormat &sf);
...
@@ -36,7 +36,7 @@ void validate_input_memfile(const SoxFormat &sf);
std
::
string
get_encoding
(
sox_encoding_t
encoding
);
std
::
string
get_encoding
(
sox_encoding_t
encoding
);
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_utils
}
// namespace sox_utils
#endif
#endif
paddlespeech/__init__.py
浏览文件 @
a3911ab5
...
@@ -14,5 +14,3 @@
...
@@ -14,5 +14,3 @@
import
_locale
import
_locale
_locale
.
_getdefaultlocale
=
(
lambda
*
args
:
[
'en_US'
,
'utf8'
])
_locale
.
_getdefaultlocale
=
(
lambda
*
args
:
[
'en_US'
,
'utf8'
])
paddlespeech/audio/README.md
浏览文件 @
a3911ab5
...
@@ -28,4 +28,4 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
...
@@ -28,4 +28,4 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
```
\ No newline at end of file
paddlespeech/audio/__init__.py
浏览文件 @
a3911ab5
...
@@ -19,4 +19,4 @@ from . import io
...
@@ -19,4 +19,4 @@ from . import io
from
.
import
metric
from
.
import
metric
from
.
import
sox_effects
from
.
import
sox_effects
from
.backends
import
load
from
.backends
import
load
from
.backends
import
save
from
.backends
import
save
\ No newline at end of file
paddlespeech/audio/_class.py
浏览文件 @
a3911ab5
import
types
import
types
class
_ClassNamespace
(
types
.
ModuleType
):
class
_ClassNamespace
(
types
.
ModuleType
):
def
__init__
(
self
,
name
):
def
__init__
(
self
,
name
):
super
(
_ClassNamespace
,
self
).
__init__
(
'paddlespeech.classes'
+
name
)
super
(
_ClassNamespace
,
self
).
__init__
(
'paddlespeech.classes'
+
name
)
...
@@ -11,6 +12,7 @@ class _ClassNamespace(types.ModuleType):
...
@@ -11,6 +12,7 @@ class _ClassNamespace(types.ModuleType):
raise
RuntimeError
(
f
'Class
{
self
.
name
}
.
{
attr
}
not registered!'
)
raise
RuntimeError
(
f
'Class
{
self
.
name
}
.
{
attr
}
not registered!'
)
return
proxy
return
proxy
class
_Classes
(
types
.
ModuleType
):
class
_Classes
(
types
.
ModuleType
):
__file__
=
'_classes.py'
__file__
=
'_classes.py'
...
@@ -43,5 +45,6 @@ class _Classes(types.ModuleType):
...
@@ -43,5 +45,6 @@ class _Classes(types.ModuleType):
"""
"""
paddlespeech
.
ops
.
load_library
(
path
)
paddlespeech
.
ops
.
load_library
(
path
)
# The classes "namespace"
# The classes "namespace"
classes
=
_Classes
()
classes
=
_Classes
()
\ No newline at end of file
paddlespeech/audio/_extension.py
浏览文件 @
a3911ab5
...
@@ -64,7 +64,8 @@ def _init_ffmpeg():
...
@@ -64,7 +64,8 @@ def _init_ffmpeg():
try
:
try
:
_load_lib
(
"libpaddlleaudio_ffmpeg"
)
_load_lib
(
"libpaddlleaudio_ffmpeg"
)
except
OSError
as
err
:
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
import
paddllespeech
.
_paddlleaudio_ffmpeg
# noqa
...
@@ -95,4 +96,4 @@ def _init_extension():
...
@@ -95,4 +96,4 @@ def _init_extension():
pass
pass
_init_extension
()
_init_extension
()
\ No newline at end of file
paddlespeech/audio/_internal/module_utils.py
浏览文件 @
a3911ab5
...
@@ -3,6 +3,7 @@ import warnings
...
@@ -3,6 +3,7 @@ import warnings
from
functools
import
wraps
from
functools
import
wraps
from
typing
import
Optional
from
typing
import
Optional
def
is_module_available
(
*
modules
:
str
)
->
bool
:
def
is_module_available
(
*
modules
:
str
)
->
bool
:
r
"""Returns if a top-level module with :attr:`name` exists *without**
r
"""Returns if a top-level module with :attr:`name` exists *without**
importing it. This is generally safer than try-catch block around a
importing it. This is generally safer than try-catch block around a
...
@@ -26,19 +27,21 @@ def requires_module(*modules: str):
...
@@ -26,19 +27,21 @@ def requires_module(*modules: str):
return
func
return
func
else
:
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
):
def
decorator
(
func
):
@
wraps
(
func
)
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
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
wrapped
return
decorator
return
decorator
def
deprecated
(
direction
:
str
,
version
:
Optional
[
str
]
=
None
):
def
deprecated
(
direction
:
str
,
version
:
Optional
[
str
]
=
None
):
"""Decorator to add deprecation message
"""Decorator to add deprecation message
Args:
Args:
direction (str): Migration steps to be given to users.
direction (str): Migration steps to be given to users.
...
@@ -51,8 +54,7 @@ def deprecated(direction: str, version: Optional[str] = None):
...
@@ -51,8 +54,7 @@ def deprecated(direction: str, version: Optional[str] = None):
message
=
(
message
=
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
has been deprecated "
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
has been deprecated "
f
'and will be removed from
{
"future"
if
version
is
None
else
version
}
release. '
f
'and will be removed from
{
"future"
if
version
is
None
else
version
}
release. '
f
"
{
direction
}
"
f
"
{
direction
}
"
)
)
warnings
.
warn
(
message
,
stacklevel
=
2
)
warnings
.
warn
(
message
,
stacklevel
=
2
)
return
func
(
*
args
,
**
kwargs
)
return
func
(
*
args
,
**
kwargs
)
...
@@ -62,7 +64,7 @@ def deprecated(direction: str, version: Optional[str] = None):
...
@@ -62,7 +64,7 @@ def deprecated(direction: str, version: Optional[str] = None):
def
is_kaldi_available
():
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
():
def
requires_kaldi
():
...
@@ -76,7 +78,8 @@ def requires_kaldi():
...
@@ -76,7 +78,8 @@ def requires_kaldi():
def
decorator
(
func
):
def
decorator
(
func
):
@
wraps
(
func
)
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
def
wrapped
(
*
args
,
**
kwargs
):
raise RuntimeError(f"
{
func
.
__module__
}.{
func
.
__name__
}
requires
kaldi
")
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires kaldi"
)
return
wrapped
return
wrapped
...
@@ -91,7 +94,8 @@ def _check_soundfile_importable():
...
@@ -91,7 +94,8 @@ def _check_soundfile_importable():
return
True
return
True
except
Exception
:
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
return
False
...
@@ -113,7 +117,8 @@ def requires_soundfile():
...
@@ -113,7 +117,8 @@ def requires_soundfile():
def
decorator
(
func
):
def
decorator
(
func
):
@
wraps
(
func
)
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
def
wrapped
(
*
args
,
**
kwargs
):
raise RuntimeError(f"
{
func
.
__module__
}.{
func
.
__name__
}
requires
soundfile
")
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires soundfile"
)
return
wrapped
return
wrapped
...
@@ -121,7 +126,7 @@ def requires_soundfile():
...
@@ -121,7 +126,7 @@ def requires_soundfile():
def
is_sox_available
():
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
():
def
requires_sox
():
...
@@ -135,8 +140,9 @@ def requires_sox():
...
@@ -135,8 +140,9 @@ def requires_sox():
def
decorator
(
func
):
def
decorator
(
func
):
@
wraps
(
func
)
@
wraps
(
func
)
def
wrapped
(
*
args
,
**
kwargs
):
def
wrapped
(
*
args
,
**
kwargs
):
raise RuntimeError(f"
{
func
.
__module__
}.{
func
.
__name__
}
requires
sox
")
raise
RuntimeError
(
f
"
{
func
.
__module__
}
.
{
func
.
__name__
}
requires sox"
)
return
wrapped
return
wrapped
return
return
\ No newline at end of file
paddlespeech/audio/_ops.py
浏览文件 @
a3911ab5
import
contextlib
import
contextlib
import
ctypes
import
ctypes
import
sys
import
os
import
os
import
sys
import
types
import
types
# Query `hasattr` only once.
# 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
@
contextlib
.
contextmanager
...
@@ -22,7 +23,7 @@ def dl_open_guard():
...
@@ -22,7 +23,7 @@ def dl_open_guard():
if
_SET_GLOBAL_FLAGS
:
if
_SET_GLOBAL_FLAGS
:
sys
.
setdlopenflags
(
old_flags
)
sys
.
setdlopenflags
(
old_flags
)
def
resolve_library_path
(
path
:
str
)
->
str
:
def
resolve_library_path
(
path
:
str
)
->
str
:
return
os
.
path
.
realpath
(
path
)
return
os
.
path
.
realpath
(
path
)
...
@@ -59,4 +60,4 @@ class _Ops(types.ModuleType):
...
@@ -59,4 +60,4 @@ class _Ops(types.ModuleType):
# The ops "namespace"
# The ops "namespace"
ops
=
_Ops
()
ops
=
_Ops
()
\ No newline at end of file
paddlespeech/audio/src/optional/optional.hpp
浏览文件 @
a3911ab5
...
@@ -32,64 +32,69 @@
...
@@ -32,64 +32,69 @@
#define TL_OPTIONAL_MSVC2015
#define TL_OPTIONAL_MSVC2015
#endif
#endif
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&
\
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
!defined(__clang__))
!defined(__clang__))
#define TL_OPTIONAL_GCC49
#define TL_OPTIONAL_GCC49
#endif
#endif
#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 &&
\
#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \
!defined(__clang__))
!defined(__clang__))
#define TL_OPTIONAL_GCC54
#define TL_OPTIONAL_GCC54
#endif
#endif
#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 &&
\
#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \
!defined(__clang__))
!defined(__clang__))
#define TL_OPTIONAL_GCC55
#define TL_OPTIONAL_GCC55
#endif
#endif
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&
\
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
!defined(__clang__))
!defined(__clang__))
// GCC < 5 doesn't support overloading on const&& for member functions
// GCC < 5 doesn't support overloading on const&& for member functions
#define TL_OPTIONAL_NO_CONSTRR
#define TL_OPTIONAL_NO_CONSTRR
// GCC < 5 doesn't support some standard C++11 type traits
// GCC < 5 doesn't support some standard C++11 type traits
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
std::has_trivial_copy_constructor<T>::value
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
// 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
// for non-copyable types
#elif (defined(__GNUC__) && __GNUC__ < 8 && \
#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
!defined(__clang__))
#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
namespace
tl
{
namespace
tl
{
namespace
detail
{
namespace
detail
{
template
<
class
T
>
template
<
class
T
>
struct
is_trivially_copy_constructible
:
std
::
is_trivially_copy_constructible
<
T
>
{};
struct
is_trivially_copy_constructible
:
std
::
is_trivially_copy_constructible
<
T
>
{};
#ifdef _GLIBCXX_VECTOR
#ifdef _GLIBCXX_VECTOR
template
<
class
T
,
class
A
>
template
<
class
T
,
class
A
>
struct
is_trivially_copy_constructible
<
std
::
vector
<
T
,
A
>>
struct
is_trivially_copy_constructible
<
std
::
vector
<
T
,
A
>>
:
std
::
is_trivially_copy_constructible
<
T
>
{};
:
std
::
is_trivially_copy_constructible
<
T
>
{};
#endif
#endif
}
}
}
}
#endif
#endif
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
\
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
tl::detail::is_trivially_copy_constructible<T>::value
tl::detail::is_trivially_copy_constructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
std::is_trivially_copy_assignable<T>::value
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
#else
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
std::is_trivially_copy_constructible<T>::value
std::is_trivially_copy_constructible<T>::value
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
std::is_trivially_copy_assignable<T>::value
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
#endif
#if __cplusplus > 201103L
#if __cplusplus > 201103L
...
@@ -97,7 +102,7 @@ namespace tl {
...
@@ -97,7 +102,7 @@ namespace tl {
#endif
#endif
// constexpr implies const in C++11, not C++14
// constexpr implies const in C++11, not C++14
#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) ||
\
#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || \
defined(TL_OPTIONAL_GCC49))
defined(TL_OPTIONAL_GCC49))
#define TL_OPTIONAL_11_CONSTEXPR
#define TL_OPTIONAL_11_CONSTEXPR
#else
#else
...
@@ -112,30 +117,35 @@ class monostate {};
...
@@ -112,30 +117,35 @@ class monostate {};
/// A tag type to tell optional to construct its value in-place
/// A tag type to tell optional to construct its value in-place
struct
in_place_t
{
struct
in_place_t
{
explicit
in_place_t
()
=
default
;
explicit
in_place_t
()
=
default
;
};
};
/// A tag to tell optional to construct its value in-place
/// A tag to tell optional to construct its value in-place
static
constexpr
in_place_t
in_place
{};
static
constexpr
in_place_t
in_place
{};
#endif
#endif
template
<
class
T
>
class
optional
;
template
<
class
T
>
class
optional
;
namespace
detail
{
namespace
detail
{
#ifndef TL_TRAITS_MUTEX
#ifndef TL_TRAITS_MUTEX
#define TL_TRAITS_MUTEX
#define TL_TRAITS_MUTEX
// C++14-style aliases for brevity
// 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
>
template
<
class
T
>
using
remove_reference_t
=
typename
std
::
remove_reference
<
T
>::
type
;
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
>
template
<
bool
E
,
class
T
=
void
>
using
enable_if_t
=
typename
std
::
enable_if
<
E
,
T
>::
type
;
using
enable_if_t
=
typename
std
::
enable_if
<
E
,
T
>::
type
;
template
<
bool
B
,
class
T
,
class
F
>
template
<
bool
B
,
class
T
,
class
F
>
using
conditional_t
=
typename
std
::
conditional
<
B
,
T
,
F
>::
type
;
using
conditional_t
=
typename
std
::
conditional
<
B
,
T
,
F
>::
type
;
// std::conjunction from C++17
// std::conjunction from C++17
template
<
class
...
>
struct
conjunction
:
std
::
true_type
{};
template
<
class
...
>
template
<
class
B
>
struct
conjunction
<
B
>
:
B
{};
struct
conjunction
:
std
::
true_type
{};
template
<
class
B
>
struct
conjunction
<
B
>
:
B
{};
template
<
class
B
,
class
...
Bs
>
template
<
class
B
,
class
...
Bs
>
struct
conjunction
<
B
,
Bs
...
>
struct
conjunction
<
B
,
Bs
...
>
:
std
::
conditional
<
bool
(
B
::
value
),
conjunction
<
Bs
...
>
,
B
>::
type
{};
:
std
::
conditional
<
bool
(
B
::
value
),
conjunction
<
Bs
...
>
,
B
>::
type
{};
...
@@ -148,56 +158,72 @@ struct conjunction<B, Bs...>
...
@@ -148,56 +158,72 @@ struct conjunction<B, Bs...>
// which results in a hard-error when using it in a noexcept expression
// 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.
// in some cases. This is a check to workaround the common failing case.
#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
#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
>
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
>
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
>
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
>
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
>
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
>
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
>
template
<
class
T
>
struct
is_const_or_const_ref
<
T
const
&>
:
std
::
true_type
{};
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
<
T
const
>
:
std
::
true_type
{};
#endif
#endif
// std::invoke from C++17
// std::invoke from C++17
// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
// 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
#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
typename
=
enable_if_t
<!
(
is_pointer_to_non_const_member_func
<
Fn
>
::
value
typename
=
enable_if_t
<!
(
is_pointer_to_non_const_member_func
<
Fn
>
::
value
&&
&&
is_const_or_const_ref
<
Args
...
>::
value
)
>
,
is_const_or_const_ref
<
Args
...
>::
value
)
>
,
#endif
#endif
typename
=
enable_if_t
<
std
::
is_member_pointer
<
decay_t
<
Fn
>>::
value
>
,
typename
=
enable_if_t
<
std
::
is_member_pointer
<
decay_t
<
Fn
>>::
value
>
,
int
=
0
>
int
=
0
>
constexpr
auto
invoke
(
Fn
&&
f
,
Args
&&
...
args
)
noexcept
(
constexpr
auto
invoke
(
Fn
&&
f
,
Args
&&
...
args
)
noexcept
(
noexcept
(
std
::
mem_fn
(
f
)(
std
::
forward
<
Args
>
(
args
)...)))
noexcept
(
std
::
mem_fn
(
f
)(
std
::
forward
<
Args
>
(
args
)...)))
->
decltype
(
std
::
mem_fn
(
f
)(
std
::
forward
<
Args
>
(
args
)...))
{
->
decltype
(
std
::
mem_fn
(
f
)(
std
::
forward
<
Args
>
(
args
)...))
{
return
std
::
mem_fn
(
f
)(
std
::
forward
<
Args
>
(
args
)...);
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
>>
typename
=
enable_if_t
<!
std
::
is_member_pointer
<
decay_t
<
Fn
>
>::
value
>>
constexpr
auto
invoke
(
Fn
&&
f
,
Args
&&
...
args
)
noexcept
(
constexpr
auto
invoke
(
Fn
&&
f
,
Args
&&
...
args
)
noexcept
(
noexcept
(
std
::
forward
<
Fn
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...)))
noexcept
(
std
::
forward
<
Fn
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...)))
->
decltype
(
std
::
forward
<
Fn
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...))
{
->
decltype
(
std
::
forward
<
Fn
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...))
{
return
std
::
forward
<
Fn
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...);
return
std
::
forward
<
Fn
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...);
}
}
// std::invoke_result from C++17
// 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
>
template
<
class
F
,
class
...
Us
>
struct
invoke_result_impl
<
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
...
>
{
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
>
template
<
class
F
,
class
...
Us
>
...
@@ -208,9 +234,11 @@ using invoke_result_t = typename invoke_result<F, Us...>::type;
...
@@ -208,9 +234,11 @@ using invoke_result_t = typename invoke_result<F, Us...>::type;
#if defined(_MSC_VER) && _MSC_VER <= 1900
#if defined(_MSC_VER) && _MSC_VER <= 1900
// TODO make a version which works with MSVC 2015
// 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
#else
// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
namespace
swap_adl_tests
{
namespace
swap_adl_tests
{
...
@@ -218,18 +246,23 @@ namespace swap_adl_tests {
...
@@ -218,18 +246,23 @@ namespace swap_adl_tests {
// signature)
// signature)
struct
tag
{};
struct
tag
{};
template
<
class
T
>
tag
swap
(
T
&
,
T
&
);
template
<
class
T
>
template
<
class
T
,
std
::
size_t
N
>
tag
swap
(
T
(
&
a
)[
N
],
T
(
&
b
)[
N
]);
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
// helper functions to test if an unqualified swap is possible, and if it
// becomes std::swap
// becomes std::swap
template
<
class
,
class
>
std
::
false_type
can_swap
(...)
noexcept
(
false
);
template
<
class
,
class
>
template
<
class
T
,
class
U
,
std
::
false_type
can_swap
(...)
noexcept
(
false
);
template
<
class
T
,
class
U
,
class
=
decltype
(
swap
(
std
::
declval
<
T
&
>(),
std
::
declval
<
U
&>
()))
>
class
=
decltype
(
swap
(
std
::
declval
<
T
&
>(),
std
::
declval
<
U
&>
()))
>
std
::
true_type
can_swap
(
int
)
noexcept
(
noexcept
(
swap
(
std
::
declval
<
T
&>
(),
std
::
true_type
can_swap
(
int
)
noexcept
(
noexcept
(
swap
(
std
::
declval
<
T
&>
(),
std
::
declval
<
U
&>
())));
std
::
declval
<
U
&>
())));
template
<
class
,
class
>
std
::
false_type
uses_std
(...);
template
<
class
,
class
>
std
::
false_type
uses_std
(...);
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
std
::
is_same
<
decltype
(
swap
(
std
::
declval
<
T
&>
(),
std
::
declval
<
U
&>
())),
tag
>
std
::
is_same
<
decltype
(
swap
(
std
::
declval
<
T
&>
(),
std
::
declval
<
U
&>
())),
tag
>
uses_std
(
int
);
uses_std
(
int
);
...
@@ -246,7 +279,7 @@ struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
...
@@ -246,7 +279,7 @@ struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
struct
is_adl_swap_noexcept
struct
is_adl_swap_noexcept
:
std
::
integral_constant
<
bool
,
noexcept
(
can_swap
<
T
,
U
>
(
0
))
>
{};
:
std
::
integral_constant
<
bool
,
noexcept
(
can_swap
<
T
,
U
>
(
0
))
>
{};
}
// namespace swap_adl_tests
}
// namespace swap_adl_tests
template
<
class
T
,
class
U
=
T
>
template
<
class
T
,
class
U
=
T
>
struct
is_swappable
struct
is_swappable
...
@@ -281,13 +314,20 @@ struct is_nothrow_swappable
...
@@ -281,13 +314,20 @@ struct is_nothrow_swappable
#endif
#endif
// std::void_t from C++17
// std::void_t from C++17
template
<
class
...
>
struct
voider
{
using
type
=
void
;
};
template
<
class
...
>
template
<
class
...
Ts
>
using
void_t
=
typename
voider
<
Ts
...
>::
type
;
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
// Trait for checking if a type is a tl::optional
template
<
class
T
>
struct
is_optional_impl
:
std
::
false_type
{};
template
<
class
T
>
template
<
class
T
>
struct
is_optional_impl
<
optional
<
T
>>
:
std
::
true_type
{};
struct
is_optional_impl
:
std
::
false_type
{};
template
<
class
T
>
using
is_optional
=
is_optional_impl
<
decay_t
<
T
>>
;
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
// Change void to tl::monostate
template
<
class
U
>
template
<
class
U
>
...
@@ -297,7 +337,8 @@ template <class F, class U, class = invoke_result_t<F, 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
>>>
;
using
get_map_return
=
optional
<
fixup_void
<
invoke_result_t
<
F
,
U
>>>
;
// Check if invoking F for some Us returns void
// 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
>
template
<
class
F
,
class
...
U
>
struct
returns_void_impl
<
F
,
void_t
<
invoke_result_t
<
F
,
U
...
>>
,
U
...
>
struct
returns_void_impl
<
F
,
void_t
<
invoke_result_t
<
F
,
U
...
>>
,
U
...
>
:
std
::
is_void
<
invoke_result_t
<
F
,
U
...
>>
{};
:
std
::
is_void
<
invoke_result_t
<
F
,
U
...
>>
{};
...
@@ -357,86 +398,92 @@ using enable_assign_from_other = detail::enable_if_t<
...
@@ -357,86 +398,92 @@ using enable_assign_from_other = detail::enable_if_t<
// destructible.
// destructible.
template
<
class
T
,
bool
=
::
std
::
is_trivially_destructible
<
T
>
::
value
>
template
<
class
T
,
bool
=
::
std
::
is_trivially_destructible
<
T
>
::
value
>
struct
optional_storage_base
{
struct
optional_storage_base
{
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
()
noexcept
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
)
template
<
class
...
U
>
:
m_value
(
std
::
forward
<
U
>
(
u
)...),
m_has_value
(
true
)
{}
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
(
in_place_t
,
U
&&
...
u
)
:
m_value
(
std
::
forward
<
U
>
(
u
)...),
m_has_value
(
true
)
{}
~
optional_storage_base
()
{
if
(
m_has_value
)
{
~
optional_storage_base
()
{
m_value
.
~
T
();
if
(
m_has_value
)
{
m_has_value
=
false
;
m_value
.
~
T
();
m_has_value
=
false
;
}
}
}
}
struct
dummy
{};
struct
dummy
{};
union
{
union
{
dummy
m_dummy
;
dummy
m_dummy
;
T
m_value
;
T
m_value
;
};
};
bool
m_has_value
;
bool
m_has_value
;
};
};
// This case is for when T is trivially destructible.
// This case is for when T is trivially destructible.
template
<
class
T
>
struct
optional_storage_base
<
T
,
true
>
{
template
<
class
T
>
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
()
noexcept
struct
optional_storage_base
<
T
,
true
>
{
:
m_dummy
(),
m_has_value
(
false
)
{}
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
()
noexcept
:
m_dummy
(),
m_has_value
(
false
)
{}
template
<
class
...
U
>
template
<
class
...
U
>
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
(
in_place_t
,
U
&&
...
u
)
TL_OPTIONAL_11_CONSTEXPR
optional_storage_base
(
in_place_t
,
U
&&
...
u
)
:
m_value
(
std
::
forward
<
U
>
(
u
)...),
m_has_value
(
true
)
{}
:
m_value
(
std
::
forward
<
U
>
(
u
)...),
m_has_value
(
true
)
{}
// No destructor, so this class is trivially destructible
// No destructor, so this class is trivially destructible
struct
dummy
{};
struct
dummy
{};
union
{
union
{
dummy
m_dummy
;
dummy
m_dummy
;
T
m_value
;
T
m_value
;
};
};
bool
m_has_value
=
false
;
bool
m_has_value
=
false
;
};
};
// This base class provides some handy member functions which can be used in
// This base class provides some handy member functions which can be used in
// further derived classes
// further derived classes
template
<
class
T
>
struct
optional_operations_base
:
optional_storage_base
<
T
>
{
template
<
class
T
>
using
optional_storage_base
<
T
>::
optional_storage_base
;
struct
optional_operations_base
:
optional_storage_base
<
T
>
{
using
optional_storage_base
<
T
>::
optional_storage_base
;
void
hard_reset
()
noexcept
{
get
().
~
T
();
void
hard_reset
()
noexcept
{
this
->
m_has_value
=
false
;
get
().
~
T
();
}
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
)
{
if
(
this
->
has_value
())
{
if
(
rhs
.
has_value
())
{
this
->
m_value
=
std
::
forward
<
Opt
>
(
rhs
).
get
();
}
else
{
this
->
m_value
.
~
T
();
this
->
m_has_value
=
false
;
this
->
m_has_value
=
false
;
}
}
}
else
if
(
rhs
.
has_value
())
{
template
<
class
...
Args
>
construct
(
std
::
forward
<
Opt
>
(
rhs
).
get
());
void
construct
(
Args
&&
...
args
)
noexcept
{
new
(
std
::
addressof
(
this
->
m_value
))
T
(
std
::
forward
<
Args
>
(
args
)...);
this
->
m_has_value
=
true
;
}
}
}
bool
has_value
()
const
{
return
this
->
m_has_value
;
}
template
<
class
Opt
>
void
assign
(
Opt
&&
rhs
)
{
if
(
this
->
has_value
())
{
if
(
rhs
.
has_value
())
{
this
->
m_value
=
std
::
forward
<
Opt
>
(
rhs
).
get
();
}
else
{
this
->
m_value
.
~
T
();
this
->
m_has_value
=
false
;
}
}
else
if
(
rhs
.
has_value
())
{
construct
(
std
::
forward
<
Opt
>
(
rhs
).
get
());
}
}
TL_OPTIONAL_11_CONSTEXPR
T
&
get
()
&
{
return
this
->
m_value
;
}
bool
has_value
()
const
{
return
this
->
m_has_value
;
}
TL_OPTIONAL_11_CONSTEXPR
const
T
&
get
()
const
&
{
return
this
->
m_value
;
}
TL_OPTIONAL_11_CONSTEXPR
T
&&
get
()
&&
{
return
std
::
move
(
this
->
m_value
);
}
TL_OPTIONAL_11_CONSTEXPR
T
&
get
()
&
{
return
this
->
m_value
;
}
TL_OPTIONAL_11_CONSTEXPR
const
T
&
get
()
const
&
{
return
this
->
m_value
;
}
TL_OPTIONAL_11_CONSTEXPR
T
&&
get
()
&&
{
return
std
::
move
(
this
->
m_value
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
constexpr
const
T
&&
get
()
const
&&
{
return
std
::
move
(
this
->
m_value
);
}
constexpr
const
T
&&
get
()
const
&&
{
return
std
::
move
(
this
->
m_value
);
}
#endif
#endif
};
};
...
@@ -444,27 +491,27 @@ template <class T> struct optional_operations_base : optional_storage_base<T> {
...
@@ -444,27 +491,27 @@ template <class T> struct optional_operations_base : optional_storage_base<T> {
// This specialization is for when T is trivially copy constructible
// This specialization is for when T is trivially copy constructible
template
<
class
T
,
bool
=
TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE
(
T
)>
template
<
class
T
,
bool
=
TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE
(
T
)>
struct
optional_copy_base
:
optional_operations_base
<
T
>
{
struct
optional_copy_base
:
optional_operations_base
<
T
>
{
using
optional_operations_base
<
T
>::
optional_operations_base
;
using
optional_operations_base
<
T
>::
optional_operations_base
;
};
};
// This specialization is for when T is not trivially copy constructible
// This specialization is for when T is not trivially copy constructible
template
<
class
T
>
template
<
class
T
>
struct
optional_copy_base
<
T
,
false
>
:
optional_operations_base
<
T
>
{
struct
optional_copy_base
<
T
,
false
>
:
optional_operations_base
<
T
>
{
using
optional_operations_base
<
T
>::
optional_operations_base
;
using
optional_operations_base
<
T
>::
optional_operations_base
;
optional_copy_base
()
=
default
;
optional_copy_base
()
=
default
;
optional_copy_base
(
const
optional_copy_base
&
rhs
)
optional_copy_base
(
const
optional_copy_base
&
rhs
)
:
optional_operations_base
<
T
>
()
{
:
optional_operations_base
<
T
>
()
{
if
(
rhs
.
has_value
())
{
if
(
rhs
.
has_value
())
{
this
->
construct
(
rhs
.
get
());
this
->
construct
(
rhs
.
get
());
}
else
{
}
else
{
this
->
m_has_value
=
false
;
this
->
m_has_value
=
false
;
}
}
}
}
optional_copy_base
(
optional_copy_base
&&
rhs
)
=
default
;
optional_copy_base
(
optional_copy_base
&&
rhs
)
=
default
;
optional_copy_base
&
operator
=
(
const
optional_copy_base
&
rhs
)
=
default
;
optional_copy_base
&
operator
=
(
const
optional_copy_base
&
rhs
)
=
default
;
optional_copy_base
&
operator
=
(
optional_copy_base
&&
rhs
)
=
default
;
optional_copy_base
&
operator
=
(
optional_copy_base
&&
rhs
)
=
default
;
};
};
// This class manages conditionally having a trivial move constructor
// This class manages conditionally having a trivial move constructor
...
@@ -475,51 +522,54 @@ struct optional_copy_base<T, false> : optional_operations_base<T> {
...
@@ -475,51 +522,54 @@ struct optional_copy_base<T, false> : optional_operations_base<T> {
#ifndef TL_OPTIONAL_GCC49
#ifndef TL_OPTIONAL_GCC49
template
<
class
T
,
bool
=
std
::
is_trivially_move_constructible
<
T
>
::
value
>
template
<
class
T
,
bool
=
std
::
is_trivially_move_constructible
<
T
>
::
value
>
struct
optional_move_base
:
optional_copy_base
<
T
>
{
struct
optional_move_base
:
optional_copy_base
<
T
>
{
using
optional_copy_base
<
T
>::
optional_copy_base
;
using
optional_copy_base
<
T
>::
optional_copy_base
;
};
};
#else
#else
template
<
class
T
,
bool
=
false
>
struct
optional_move_base
;
template
<
class
T
,
bool
=
false
>
struct
optional_move_base
;
#endif
#endif
template
<
class
T
>
struct
optional_move_base
<
T
,
false
>
:
optional_copy_base
<
T
>
{
template
<
class
T
>
using
optional_copy_base
<
T
>::
optional_copy_base
;
struct
optional_move_base
<
T
,
false
>
:
optional_copy_base
<
T
>
{
using
optional_copy_base
<
T
>::
optional_copy_base
;
optional_move_base
()
=
default
;
optional_move_base
(
const
optional_move_base
&
rhs
)
=
default
;
optional_move_base
()
=
default
;
optional_move_base
(
const
optional_move_base
&
rhs
)
=
default
;
optional_move_base
(
optional_move_base
&&
rhs
)
noexcept
(
std
::
is_nothrow_move_constructible
<
T
>::
value
)
{
optional_move_base
(
optional_move_base
&&
rhs
)
noexcept
(
if
(
rhs
.
has_value
())
{
std
::
is_nothrow_move_constructible
<
T
>::
value
)
{
this
->
construct
(
std
::
move
(
rhs
.
get
()));
if
(
rhs
.
has_value
())
{
}
else
{
this
->
construct
(
std
::
move
(
rhs
.
get
()));
this
->
m_has_value
=
false
;
}
else
{
}
this
->
m_has_value
=
false
;
}
}
optional_move_base
&
operator
=
(
const
optional_move_base
&
rhs
)
=
default
;
}
optional_move_base
&
operator
=
(
optional_move_base
&&
rhs
)
=
default
;
optional_move_base
&
operator
=
(
const
optional_move_base
&
rhs
)
=
default
;
optional_move_base
&
operator
=
(
optional_move_base
&&
rhs
)
=
default
;
};
};
// This class manages conditionally having a trivial copy assignment operator
// This class manages conditionally having a trivial copy assignment operator
template
<
class
T
,
bool
=
TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE
(
T
)
&&
template
<
class
T
,
TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE
(
T
)
&&
bool
=
TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE
(
T
)
&&
TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE
(
T
)>
TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE
(
T
)
&&
TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE
(
T
)>
struct
optional_copy_assign_base
:
optional_move_base
<
T
>
{
struct
optional_copy_assign_base
:
optional_move_base
<
T
>
{
using
optional_move_base
<
T
>::
optional_move_base
;
using
optional_move_base
<
T
>::
optional_move_base
;
};
};
template
<
class
T
>
template
<
class
T
>
struct
optional_copy_assign_base
<
T
,
false
>
:
optional_move_base
<
T
>
{
struct
optional_copy_assign_base
<
T
,
false
>
:
optional_move_base
<
T
>
{
using
optional_move_base
<
T
>::
optional_move_base
;
using
optional_move_base
<
T
>::
optional_move_base
;
optional_copy_assign_base
()
=
default
;
optional_copy_assign_base
()
=
default
;
optional_copy_assign_base
(
const
optional_copy_assign_base
&
rhs
)
=
default
;
optional_copy_assign_base
(
const
optional_copy_assign_base
&
rhs
)
=
default
;
optional_copy_assign_base
(
optional_copy_assign_base
&&
rhs
)
=
default
;
optional_copy_assign_base
(
optional_copy_assign_base
&&
rhs
)
=
default
;
optional_copy_assign_base
&
operator
=
(
const
optional_copy_assign_base
&
rhs
)
{
optional_copy_assign_base
&
operator
=
(
const
optional_copy_assign_base
&
rhs
)
{
this
->
assign
(
rhs
);
this
->
assign
(
rhs
);
return
*
this
;
return
*
this
;
}
}
optional_copy_assign_base
&
optional_copy_assign_base
&
operator
=
(
optional_copy_assign_base
&&
rhs
)
=
operator
=
(
optional_copy_assign_base
&&
rhs
)
=
default
;
default
;
};
};
// This class manages conditionally having a trivial move assignment operator
// This class manages conditionally having a trivial move assignment operator
...
@@ -528,79 +578,85 @@ struct optional_copy_assign_base<T, false> : optional_move_base<T> {
...
@@ -528,79 +578,85 @@ 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
// to make do with a non-trivial move assignment operator even if T is trivially
// move assignable
// move assignable
#ifndef TL_OPTIONAL_GCC49
#ifndef TL_OPTIONAL_GCC49
template
<
class
T
,
bool
=
std
::
is_trivially_destructible
<
T
>
::
value
template
<
class
T
,
&&
std
::
is_trivially_move_constructible
<
T
>::
value
bool
=
std
::
is_trivially_destructible
<
T
>
::
value
&&
std
::
is_trivially_move_assignable
<
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
>
{
struct
optional_move_assign_base
:
optional_copy_assign_base
<
T
>
{
using
optional_copy_assign_base
<
T
>::
optional_copy_assign_base
;
using
optional_copy_assign_base
<
T
>::
optional_copy_assign_base
;
};
};
#else
#else
template
<
class
T
,
bool
=
false
>
struct
optional_move_assign_base
;
template
<
class
T
,
bool
=
false
>
struct
optional_move_assign_base
;
#endif
#endif
template
<
class
T
>
template
<
class
T
>
struct
optional_move_assign_base
<
T
,
false
>
:
optional_copy_assign_base
<
T
>
{
struct
optional_move_assign_base
<
T
,
false
>
:
optional_copy_assign_base
<
T
>
{
using
optional_copy_assign_base
<
T
>::
optional_copy_assign_base
;
using
optional_copy_assign_base
<
T
>::
optional_copy_assign_base
;
optional_move_assign_base
()
=
default
;
optional_move_assign_base
()
=
default
;
optional_move_assign_base
(
const
optional_move_assign_base
&
rhs
)
=
default
;
optional_move_assign_base
(
const
optional_move_assign_base
&
rhs
)
=
default
;
optional_move_assign_base
(
optional_move_assign_base
&&
rhs
)
=
default
;
optional_move_assign_base
(
optional_move_assign_base
&&
rhs
)
=
default
;
optional_move_assign_base
&
optional_move_assign_base
&
operator
=
(
const
optional_move_assign_base
&
rhs
)
=
operator
=
(
const
optional_move_assign_base
&
rhs
)
=
default
;
default
;
optional_move_assign_base
&
optional_move_assign_base
&
operator
=
(
optional_move_assign_base
&&
rhs
)
noexcept
(
operator
=
(
optional_move_assign_base
&&
rhs
)
noexcept
(
std
::
is_nothrow_move_constructible
<
T
>::
value
std
::
is_nothrow_move_constructible
<
T
>::
value
&&
std
::
is_nothrow_move_assignable
<
T
>::
value
)
{
&&
std
::
is_nothrow_move_assignable
<
T
>::
value
)
{
this
->
assign
(
std
::
move
(
rhs
));
this
->
assign
(
std
::
move
(
rhs
));
return
*
this
;
return
*
this
;
}
}
};
};
// optional_delete_ctor_base will conditionally delete copy and move
// optional_delete_ctor_base will conditionally delete copy and move
// constructors depending on whether T is copy/move constructible
// 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
>
bool
EnableMove
=
std
::
is_move_constructible
<
T
>::
value
>
struct
optional_delete_ctor_base
{
struct
optional_delete_ctor_base
{
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
const
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
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
default
;
optional_delete_ctor_base
&
optional_delete_ctor_base
&
operator
=
(
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&&
)
noexcept
=
default
;
};
};
template
<
class
T
>
struct
optional_delete_ctor_base
<
T
,
true
,
false
>
{
template
<
class
T
>
optional_delete_ctor_base
()
=
default
;
struct
optional_delete_ctor_base
<
T
,
true
,
false
>
{
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
delete
;
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
delete
;
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
optional_delete_ctor_base
&
default
;
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
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
>
optional_delete_ctor_base
()
=
default
;
struct
optional_delete_ctor_base
<
T
,
false
,
true
>
{
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
delete
;
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
delete
;
optional_delete_ctor_base
&
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
optional_delete_ctor_base
&
default
;
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
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
>
optional_delete_ctor_base
()
=
default
;
struct
optional_delete_ctor_base
<
T
,
false
,
false
>
{
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
delete
;
optional_delete_ctor_base
()
=
default
;
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
delete
;
optional_delete_ctor_base
(
const
optional_delete_ctor_base
&
)
=
delete
;
optional_delete_ctor_base
&
optional_delete_ctor_base
(
optional_delete_ctor_base
&&
)
noexcept
=
delete
;
operator
=
(
const
optional_delete_ctor_base
&
)
=
default
;
optional_delete_ctor_base
&
operator
=
(
const
optional_delete_ctor_base
&
)
=
optional_delete_ctor_base
&
default
;
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
optional_delete_ctor_base
&
operator
=
(
optional_delete_ctor_base
&&
)
noexcept
=
default
;
};
};
// optional_delete_assign_base will conditionally delete copy and move
// optional_delete_assign_base will conditionally delete copy and move
...
@@ -611,64 +667,67 @@ template <class T,
...
@@ -611,64 +667,67 @@ template <class T,
bool
EnableMove
=
(
std
::
is_move_constructible
<
T
>::
value
&&
bool
EnableMove
=
(
std
::
is_move_constructible
<
T
>::
value
&&
std
::
is_move_assignable
<
T
>::
value
)
>
std
::
is_move_assignable
<
T
>::
value
)
>
struct
optional_delete_assign_base
{
struct
optional_delete_assign_base
{
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
default
;
optional_delete_assign_base
&
optional_delete_assign_base
&
operator
=
(
operator
=
(
const
optional_delete_assign_base
&
)
=
default
;
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
&
optional_delete_assign_base
&
operator
=
(
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
optional_delete_assign_base
&&
)
noexcept
=
default
;
};
};
template
<
class
T
>
struct
optional_delete_assign_base
<
T
,
true
,
false
>
{
template
<
class
T
>
optional_delete_assign_base
()
=
default
;
struct
optional_delete_assign_base
<
T
,
true
,
false
>
{
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
optional_delete_assign_base
&
default
;
operator
=
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&
const
optional_delete_assign_base
&
)
=
default
;
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
delete
;
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
>
optional_delete_assign_base
()
=
default
;
struct
optional_delete_assign_base
<
T
,
false
,
true
>
{
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
optional_delete_assign_base
&
default
;
operator
=
(
const
optional_delete_assign_base
&
)
=
delete
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&
const
optional_delete_assign_base
&
)
=
delete
;
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
default
;
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
>
optional_delete_assign_base
()
=
default
;
struct
optional_delete_assign_base
<
T
,
false
,
false
>
{
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
optional_delete_assign_base
()
=
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
optional_delete_assign_base
(
const
optional_delete_assign_base
&
)
=
default
;
default
;
optional_delete_assign_base
(
optional_delete_assign_base
&&
)
noexcept
=
optional_delete_assign_base
&
default
;
operator
=
(
const
optional_delete_assign_base
&
)
=
delete
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&
const
optional_delete_assign_base
&
)
=
delete
;
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
delete
;
optional_delete_assign_base
&
operator
=
(
optional_delete_assign_base
&&
)
noexcept
=
delete
;
};
};
}
// namespace detail
}
// namespace detail
/// A tag type to represent an empty optional
/// A tag type to represent an empty optional
struct
nullopt_t
{
struct
nullopt_t
{
struct
do_not_use
{};
struct
do_not_use
{};
constexpr
explicit
nullopt_t
(
do_not_use
,
do_not_use
)
noexcept
{}
constexpr
explicit
nullopt_t
(
do_not_use
,
do_not_use
)
noexcept
{}
};
};
/// Represents an empty optional
/// Represents an empty optional
static
constexpr
nullopt_t
nullopt
{
nullopt_t
::
do_not_use
{},
static
constexpr
nullopt_t
nullopt
{
nullopt_t
::
do_not_use
{},
nullopt_t
::
do_not_use
{}};
nullopt_t
::
do_not_use
{}};
class
bad_optional_access
:
public
std
::
exception
{
class
bad_optional_access
:
public
std
::
exception
{
public:
public:
bad_optional_access
()
=
default
;
bad_optional_access
()
=
default
;
const
char
*
what
()
const
noexcept
{
return
"Optional has no value"
;
}
const
char
*
what
()
const
noexcept
{
return
"Optional has no value"
;
}
};
};
/// An optional object is an object that contains the storage for another
/// An optional object is an object that contains the storage for another
...
@@ -681,793 +740,823 @@ template <class T>
...
@@ -681,793 +740,823 @@ template <class T>
class
optional
:
private
detail
::
optional_move_assign_base
<
T
>
,
class
optional
:
private
detail
::
optional_move_assign_base
<
T
>
,
private
detail
::
optional_delete_ctor_base
<
T
>
,
private
detail
::
optional_delete_ctor_base
<
T
>
,
private
detail
::
optional_delete_assign_base
<
T
>
{
private
detail
::
optional_delete_assign_base
<
T
>
{
using
base
=
detail
::
optional_move_assign_base
<
T
>
;
using
base
=
detail
::
optional_move_assign_base
<
T
>
;
static_assert
(
!
std
::
is_same
<
T
,
in_place_t
>::
value
,
static_assert
(
!
std
::
is_same
<
T
,
in_place_t
>::
value
,
"instantiation of optional with in_place_t is ill-formed"
);
"instantiation of optional with in_place_t is ill-formed"
);
static_assert
(
!
std
::
is_same
<
detail
::
decay_t
<
T
>
,
nullopt_t
>::
value
,
static_assert
(
!
std
::
is_same
<
detail
::
decay_t
<
T
>
,
nullopt_t
>::
value
,
"instantiation of optional with nullopt_t is ill-formed"
);
"instantiation of optional with nullopt_t is ill-formed"
);
public:
public:
// The different versions for C++14 and 11 are needed because deduced return
// 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
// types are not SFINAE-safe. This provides better support for things like
// generic lambdas. C.f.
// generic lambdas. C.f.
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&
\
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation which returns an optional on the stored
/// Carries out some operation which returns an optional on the stored
/// object if there is one.
/// object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
template
<
class
F
>
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
result
(
nullopt
);
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
T
&&>
;
template
<
class
F
>
static_assert
(
detail
::
is_optional
<
result
>::
value
,
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
"F must return an optional"
);
using
result
=
detail
::
invoke_result_t
<
F
,
T
&&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
"F must return an optional"
);
:
result
(
nullopt
);
}
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
:
result
(
nullopt
);
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
}
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
:
result
(
nullopt
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
}
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
template
<
class
F
>
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&&>
;
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
return
has_value
()
}
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
}
#endif
#endif
#else
#else
/// Carries out some operation which returns an optional on the stored
/// Carries out some operation which returns an optional on the stored
/// object if there is one.
/// object if there is one.
template
<
class
F
>
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
&>
;
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
:
result
(
nullopt
);
}
}
template
<
class
F
>
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
(
using
result
=
detail
::
invoke_result_t
<
F
,
T
&&>
;
F
&&
f
)
&&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
T
&&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
return
has_value
()
}
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
result
(
nullopt
);
template
<
class
F
>
}
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&>
and_then
(
F
&&
f
)
const
&
{
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
template
<
class
F
>
static_assert
(
detail
::
is_optional
<
result
>::
value
,
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&>
and_then
(
F
&&
f
)
const
&
{
"F must return an optional"
);
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
"F must return an optional"
);
:
result
(
nullopt
);
}
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
template
<
class
F
>
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&&>
and_then
(
F
&&
f
)
const
&&
{
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&&>
and_then
(
F
&&
f
)
const
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&&>
;
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
return
has_value
()
:
result
(
nullopt
);
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
}
:
result
(
nullopt
);
}
#endif
#endif
#endif
#endif
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&
\
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
/// 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
>
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
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
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
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
&
{
}
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
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
#else
/// Carries out some operation on the stored object if there is one.
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
std
::
declval
<
F
&&>
()))
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&
{
map
(
F
&&
f
)
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
std
::
declval
<
F
&&>
()))
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&&
{
map
(
F
&&
f
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
const
&
{
map
(
F
&&
f
)
const
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
const
&&
{
map
(
F
&&
f
)
const
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
#endif
#endif
#endif
#endif
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&
\
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
/// 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
>
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
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
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
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
&
{
}
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
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
#else
/// Carries out some operation on the stored object if there is one.
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
std
::
declval
<
F
&&>
()))
optional_map_impl
(
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&
{
transform
(
F
&&
f
)
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
std
::
declval
<
F
&&>
()))
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&&
{
transform
(
F
&&
f
)
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&
{
transform
(
F
&&
f
)
const
&
{
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
constexpr
decltype
(
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&&
{
transform
(
F
&&
f
)
const
&&
{
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
#endif
#endif
#endif
#endif
/// Calls `f` if the optional is empty
/// Calls `f` if the optional is empty
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
if
(
has_value
())
if
(
has_value
())
return
*
this
;
return
*
this
;
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
}
}
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
&&
{
optional
<
T
>
or_else
(
F
&&
f
)
&&
{
if
(
has_value
())
if
(
has_value
())
return
std
::
move
(
*
this
);
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
}
}
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&
{
optional
<
T
>
or_else
(
F
&&
f
)
const
&
{
if
(
has_value
())
if
(
has_value
())
return
*
this
;
return
*
this
;
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
const
&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
const
&
{
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
if
(
has_value
())
if
(
has_value
())
return
std
::
move
(
*
this
);
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
}
}
#endif
#endif
/// Maps the stored value with `f` if there is one, otherwise returns `u`.
/// 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
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
U
map_or
(
F
&&
f
,
U
&&
u
)
&
{
:
std
::
forward
<
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
)
&&
{
template
<
class
F
,
class
U
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
U
map_or
(
F
&&
f
,
U
&&
u
)
&&
{
:
std
::
forward
<
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
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&
{
:
std
::
forward
<
U
>
(
u
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
std
::
forward
<
U
>
(
u
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
template
<
class
F
,
class
U
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
:
std
::
forward
<
U
>
(
u
);
return
has_value
()
}
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
);
}
#endif
#endif
/// Maps the stored value with `f` if there is one, otherwise calls
/// Maps the stored value with `f` if there is one, otherwise calls
/// `u` and returns the result.
/// `u` and returns the result.
template
<
class
F
,
class
U
>
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
&
{
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
std
::
forward
<
U
>
(
u
)();
:
std
::
forward
<
U
>
(
u
)();
}
}
template
<
class
F
,
class
U
>
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
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
()
:
std
::
forward
<
U
>
(
u
)();
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
}
:
std
::
forward
<
U
>
(
u
)();
}
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&
{
template
<
class
F
,
class
U
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&
{
:
std
::
forward
<
U
>
(
u
)();
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
std
::
forward
<
U
>
(
u
)();
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&&
{
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
()
:
std
::
forward
<
U
>
(
u
)();
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
}
:
std
::
forward
<
U
>
(
u
)();
}
#endif
#endif
/// Returns `u` if `*this` has a value, otherwise an empty optional.
/// Returns `u` if `*this` has a value, otherwise an empty optional.
template
<
class
U
>
template
<
class
U
>
constexpr
optional
<
typename
std
::
decay
<
U
>::
type
>
conjunction
(
U
&&
u
)
const
{
constexpr
optional
<
typename
std
::
decay
<
U
>::
type
>
conjunction
(
U
&&
u
)
const
{
using
result
=
optional
<
detail
::
decay_t
<
U
>>
;
using
result
=
optional
<
detail
::
decay_t
<
U
>>
;
return
has_value
()
?
result
{
u
}
:
result
{
nullopt
};
return
has_value
()
?
result
{
u
}
:
result
{
nullopt
};
}
}
/// Returns `rhs` if `*this` is empty, otherwise the current value.
/// Returns `rhs` if `*this` is empty, otherwise the current value.
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&
{
return
has_value
()
?
*
this
:
rhs
;
return
has_value
()
?
*
this
:
rhs
;
}
}
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&
{
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&
{
return
has_value
()
?
*
this
:
rhs
;
return
has_value
()
?
*
this
:
rhs
;
}
}
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&&
{
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
}
}
#endif
#endif
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&
{
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
}
}
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&
{
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&
{
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
}
}
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&&
{
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
}
}
#endif
#endif
/// Takes the value out of the optional, leaving it empty
/// Takes the value out of the optional, leaving it empty
optional
take
()
{
optional
take
()
{
optional
ret
=
std
::
move
(
*
this
);
optional
ret
=
std
::
move
(
*
this
);
reset
();
reset
();
return
ret
;
return
ret
;
}
}
using
value_type
=
T
;
using
value_type
=
T
;
/// Constructs an optional that does not contain a value.
/// Constructs an optional that does not contain a value.
constexpr
optional
()
noexcept
=
default
;
constexpr
optional
()
noexcept
=
default
;
constexpr
optional
(
nullopt_t
)
noexcept
{}
constexpr
optional
(
nullopt_t
)
noexcept
{}
/// Copy constructor
/// Copy constructor
///
///
/// If `rhs` contains a value, the stored value is direct-initialized with
/// If `rhs` contains a value, the stored value is direct-initialized with
/// it. Otherwise, the constructed optional is empty.
/// it. Otherwise, the constructed optional is empty.
TL_OPTIONAL_11_CONSTEXPR
optional
(
const
optional
&
rhs
)
=
default
;
TL_OPTIONAL_11_CONSTEXPR
optional
(
const
optional
&
rhs
)
=
default
;
/// Move constructor
/// Move constructor
///
///
/// If `rhs` contains a value, the stored value is direct-initialized with
/// If `rhs` contains a value, the stored value is direct-initialized with
/// it. Otherwise, the constructed optional is empty.
/// it. Otherwise, the constructed optional is empty.
TL_OPTIONAL_11_CONSTEXPR
optional
(
optional
&&
rhs
)
=
default
;
TL_OPTIONAL_11_CONSTEXPR
optional
(
optional
&&
rhs
)
=
default
;
/// Constructs the stored value in-place using the given arguments.
/// Constructs the stored value in-place using the given arguments.
template
<
class
...
Args
>
template
<
class
...
Args
>
constexpr
explicit
optional
(
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
,
Args
&&
...
args
)
in_place_t
>
,
:
base
(
in_place
,
std
::
forward
<
Args
>
(
args
)...)
{}
Args
&&
...
args
)
:
base
(
in_place
,
std
::
forward
<
Args
>
(
args
)...)
{}
template
<
class
U
,
class
...
Args
>
TL_OPTIONAL_11_CONSTEXPR
explicit
optional
(
template
<
class
U
,
class
...
Args
>
detail
::
enable_if_t
<
std
::
is_constructible
<
T
,
std
::
initializer_list
<
U
>
&
,
TL_OPTIONAL_11_CONSTEXPR
explicit
optional
(
Args
&&
...
>::
value
,
detail
::
enable_if_t
<
std
::
is_constructible
<
T
,
in_place_t
>
,
std
::
initializer_list
<
U
>
&
,
std
::
initializer_list
<
U
>
il
,
Args
&&
...
args
)
{
Args
&&
...
>::
value
,
this
->
construct
(
il
,
std
::
forward
<
Args
>
(
args
)...);
in_place_t
>
,
}
std
::
initializer_list
<
U
>
il
,
Args
&&
...
args
)
{
/// Constructs the stored value with `u`.
this
->
construct
(
il
,
std
::
forward
<
Args
>
(
args
)...);
template
<
}
class
U
=
T
,
detail
::
enable_if_t
<
std
::
is_convertible
<
U
&&
,
T
>
::
value
>
*
=
nullptr
,
/// Constructs the stored value with `u`.
detail
::
enable_forward_value
<
T
,
U
>
*
=
nullptr
>
template
<
constexpr
optional
(
U
&&
u
)
:
base
(
in_place
,
std
::
forward
<
U
>
(
u
))
{}
class
U
=
T
,
detail
::
enable_if_t
<
std
::
is_convertible
<
U
&&
,
T
>
::
value
>
*
=
nullptr
,
template
<
detail
::
enable_forward_value
<
T
,
U
>
*
=
nullptr
>
class
U
=
T
,
constexpr
optional
(
U
&&
u
)
:
base
(
in_place
,
std
::
forward
<
U
>
(
u
))
{}
detail
::
enable_if_t
<!
std
::
is_convertible
<
U
&&
,
T
>
::
value
>
*
=
nullptr
,
detail
::
enable_forward_value
<
T
,
U
>
*
=
nullptr
>
template
<
constexpr
explicit
optional
(
U
&&
u
)
:
base
(
in_place
,
std
::
forward
<
U
>
(
u
))
{}
class
U
=
T
,
detail
::
enable_if_t
<!
std
::
is_convertible
<
U
&&
,
T
>
::
value
>
*
=
nullptr
,
/// Converting copy constructor.
detail
::
enable_forward_value
<
T
,
U
>
*
=
nullptr
>
template
<
constexpr
explicit
optional
(
U
&&
u
)
:
base
(
in_place
,
std
::
forward
<
U
>
(
u
))
{}
class
U
,
detail
::
enable_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
,
detail
::
enable_if_t
<
std
::
is_convertible
<
const
U
&
,
T
>::
value
>
*
=
nullptr
>
/// Converting copy constructor.
optional
(
const
optional
<
U
>
&
rhs
)
{
template
<
class
U
,
if
(
rhs
.
has_value
())
{
detail
::
enable_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
,
this
->
construct
(
*
rhs
);
detail
::
enable_if_t
<
std
::
is_convertible
<
const
U
&
,
T
>::
value
>
*
=
}
nullptr
>
}
optional
(
const
optional
<
U
>
&
rhs
)
{
if
(
rhs
.
has_value
())
{
template
<
class
U
,
detail
::
enable_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
,
this
->
construct
(
*
rhs
);
detail
::
enable_if_t
<!
std
::
is_convertible
<
const
U
&
,
T
>::
value
>
*
=
}
nullptr
>
}
explicit
optional
(
const
optional
<
U
>
&
rhs
)
{
if
(
rhs
.
has_value
())
{
template
<
class
U
,
this
->
construct
(
*
rhs
);
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
)
{
/// Converting move constructor.
if
(
rhs
.
has_value
())
{
template
<
this
->
construct
(
*
rhs
);
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
())
{
/// Converting move constructor.
this
->
construct
(
std
::
move
(
*
rhs
));
template
<
}
class
U
,
}
detail
::
enable_from_other
<
T
,
U
,
U
&&
>
*
=
nullptr
,
detail
::
enable_if_t
<
std
::
is_convertible
<
U
&&
,
T
>::
value
>
*
=
nullptr
>
template
<
optional
(
optional
<
U
>
&&
rhs
)
{
class
U
,
detail
::
enable_from_other
<
T
,
U
,
U
&&
>
*
=
nullptr
,
if
(
rhs
.
has_value
())
{
detail
::
enable_if_t
<!
std
::
is_convertible
<
U
&&
,
T
>::
value
>
*
=
nullptr
>
this
->
construct
(
std
::
move
(
*
rhs
));
explicit
optional
(
optional
<
U
>
&&
rhs
)
{
}
if
(
rhs
.
has_value
())
{
}
this
->
construct
(
std
::
move
(
*
rhs
));
}
template
<
}
class
U
,
detail
::
enable_from_other
<
T
,
U
,
U
&&
>
*
=
nullptr
,
/// Destroys the stored value if there is one.
detail
::
enable_if_t
<!
std
::
is_convertible
<
U
&&
,
T
>::
value
>
*
=
nullptr
>
~
optional
()
=
default
;
explicit
optional
(
optional
<
U
>
&&
rhs
)
{
if
(
rhs
.
has_value
())
{
/// Assignment to empty.
this
->
construct
(
std
::
move
(
*
rhs
));
///
}
/// Destroys the current value if there is one.
}
optional
&
operator
=
(
nullopt_t
)
noexcept
{
if
(
has_value
())
{
/// Destroys the stored value if there is one.
this
->
m_value
.
~
T
();
~
optional
()
=
default
;
this
->
m_has_value
=
false
;
}
/// Assignment to empty.
///
return
*
this
;
/// Destroys the current value if there is one.
}
optional
&
operator
=
(
nullopt_t
)
noexcept
{
if
(
has_value
())
{
/// Copy assignment.
this
->
m_value
.
~
T
();
///
this
->
m_has_value
=
false
;
/// Copies the value from `rhs` if there is one. Otherwise resets the stored
}
/// value in `*this`.
optional
&
operator
=
(
const
optional
&
rhs
)
=
default
;
return
*
this
;
}
/// Move assignment.
///
/// Copy assignment.
/// Moves the value from `rhs` if there is one. Otherwise resets the stored
///
/// value in `*this`.
/// Copies the value from `rhs` if there is one. Otherwise resets the stored
optional
&
operator
=
(
optional
&&
rhs
)
=
default
;
/// value in `*this`.
optional
&
operator
=
(
const
optional
&
rhs
)
=
default
;
/// Assigns the stored value from `u`, destroying the old value if there was
/// one.
/// Move assignment.
template
<
class
U
=
T
,
detail
::
enable_assign_forward
<
T
,
U
>
*
=
nullptr
>
///
optional
&
operator
=
(
U
&&
u
)
{
/// Moves the value from `rhs` if there is one. Otherwise resets the stored
if
(
has_value
())
{
/// value in `*this`.
this
->
m_value
=
std
::
forward
<
U
>
(
u
);
optional
&
operator
=
(
optional
&&
rhs
)
=
default
;
}
else
{
this
->
construct
(
std
::
forward
<
U
>
(
u
));
/// Assigns the stored value from `u`, destroying the old value if there was
}
/// one.
template
<
class
U
=
T
,
detail
::
enable_assign_forward
<
T
,
U
>
*
=
nullptr
>
return
*
this
;
optional
&
operator
=
(
U
&&
u
)
{
}
if
(
has_value
())
{
this
->
m_value
=
std
::
forward
<
U
>
(
u
);
/// Converting copy assignment operator.
}
else
{
///
this
->
construct
(
std
::
forward
<
U
>
(
u
));
/// Copies the value from `rhs` if there is one. Otherwise resets the stored
}
/// value in `*this`.
template
<
class
U
,
return
*
this
;
detail
::
enable_assign_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
>
}
optional
&
operator
=
(
const
optional
<
U
>
&
rhs
)
{
if
(
has_value
())
{
/// Converting copy assignment operator.
if
(
rhs
.
has_value
())
{
///
this
->
m_value
=
*
rhs
;
/// Copies the value from `rhs` if there is one. Otherwise resets the stored
}
else
{
/// value in `*this`.
this
->
hard_reset
();
template
<
class
U
,
}
detail
::
enable_assign_from_other
<
T
,
U
,
const
U
&
>
*
=
nullptr
>
}
optional
&
operator
=
(
const
optional
<
U
>
&
rhs
)
{
if
(
has_value
())
{
if
(
rhs
.
has_value
())
{
if
(
rhs
.
has_value
())
{
this
->
construct
(
*
rhs
);
this
->
m_value
=
*
rhs
;
}
}
else
{
this
->
hard_reset
();
return
*
this
;
}
}
}
// TODO check exception guarantee
if
(
rhs
.
has_value
())
{
/// Converting move assignment operator.
this
->
construct
(
*
rhs
);
///
}
/// Moves the value from `rhs` if there is one. Otherwise resets the stored
/// value in `*this`.
return
*
this
;
template
<
class
U
,
detail
::
enable_assign_from_other
<
T
,
U
,
U
>
*
=
nullptr
>
}
optional
&
operator
=
(
optional
<
U
>
&&
rhs
)
{
if
(
has_value
())
{
// TODO check exception guarantee
if
(
rhs
.
has_value
())
{
/// Converting move assignment operator.
this
->
m_value
=
std
::
move
(
*
rhs
);
///
}
else
{
/// Moves the value from `rhs` if there is one. Otherwise resets the stored
this
->
hard_reset
();
/// value in `*this`.
}
template
<
class
U
,
detail
::
enable_assign_from_other
<
T
,
U
,
U
>
*
=
nullptr
>
}
optional
&
operator
=
(
optional
<
U
>
&&
rhs
)
{
if
(
has_value
())
{
if
(
rhs
.
has_value
())
{
if
(
rhs
.
has_value
())
{
this
->
construct
(
std
::
move
(
*
rhs
));
this
->
m_value
=
std
::
move
(
*
rhs
);
}
}
else
{
this
->
hard_reset
();
return
*
this
;
}
}
}
/// Constructs the value in-place, destroying the current one if there is
if
(
rhs
.
has_value
())
{
/// one.
this
->
construct
(
std
::
move
(
*
rhs
));
template
<
class
...
Args
>
T
&
emplace
(
Args
&&
...
args
)
{
}
static_assert
(
std
::
is_constructible
<
T
,
Args
&&
...
>::
value
,
"T must be constructible with Args"
);
return
*
this
;
}
*
this
=
nullopt
;
this
->
construct
(
std
::
forward
<
Args
>
(
args
)...);
/// Constructs the value in-place, destroying the current one if there is
return
value
();
/// one.
}
template
<
class
...
Args
>
T
&
emplace
(
Args
&&
...
args
)
{
template
<
class
U
,
class
...
Args
>
static_assert
(
std
::
is_constructible
<
T
,
Args
&&
...
>::
value
,
detail
::
enable_if_t
<
"T must be constructible with Args"
);
std
::
is_constructible
<
T
,
std
::
initializer_list
<
U
>
&
,
Args
&&
...
>::
value
,
T
&>
*
this
=
nullopt
;
emplace
(
std
::
initializer_list
<
U
>
il
,
Args
&&
...
args
)
{
this
->
construct
(
std
::
forward
<
Args
>
(
args
)...);
*
this
=
nullopt
;
return
value
();
this
->
construct
(
il
,
std
::
forward
<
Args
>
(
args
)...);
}
return
value
();
}
template
<
class
U
,
class
...
Args
>
detail
::
enable_if_t
<
/// Swaps this optional with the other.
std
::
is_constructible
<
T
,
std
::
initializer_list
<
U
>
&
,
Args
&&
...
>::
value
,
///
T
&>
/// If neither optionals have a value, nothing happens.
emplace
(
std
::
initializer_list
<
U
>
il
,
Args
&&
...
args
)
{
/// If both have a value, the values are swapped.
*
this
=
nullopt
;
/// If one has a value, it is moved to the other and the movee is left
this
->
construct
(
il
,
std
::
forward
<
Args
>
(
args
)...);
/// valueless.
return
value
();
void
}
swap
(
optional
&
rhs
)
noexcept
(
std
::
is_nothrow_move_constructible
<
T
>::
value
&&
detail
::
is_nothrow_swappable
<
T
>::
value
)
{
/// Swaps this optional with the other.
using
std
::
swap
;
///
if
(
has_value
())
{
/// If neither optionals have a value, nothing happens.
if
(
rhs
.
has_value
())
{
/// If both have a value, the values are swapped.
swap
(
**
this
,
*
rhs
);
/// If one has a value, it is moved to the other and the movee is left
}
else
{
/// valueless.
new
(
std
::
addressof
(
rhs
.
m_value
))
T
(
std
::
move
(
this
->
m_value
));
void
swap
(
optional
&
rhs
)
noexcept
(
this
->
m_value
.
T
::~
T
();
std
::
is_nothrow_move_constructible
<
T
>::
value
}
&&
detail
::
is_nothrow_swappable
<
T
>::
value
)
{
}
else
if
(
rhs
.
has_value
())
{
using
std
::
swap
;
new
(
std
::
addressof
(
this
->
m_value
))
T
(
std
::
move
(
rhs
.
m_value
));
if
(
has_value
())
{
rhs
.
m_value
.
T
::~
T
();
if
(
rhs
.
has_value
())
{
}
swap
(
**
this
,
*
rhs
);
swap
(
this
->
m_has_value
,
rhs
.
m_has_value
);
}
else
{
}
new
(
std
::
addressof
(
rhs
.
m_value
))
T
(
std
::
move
(
this
->
m_value
));
this
->
m_value
.
T
::~
T
();
/// Returns a pointer to the stored value
}
constexpr
const
T
*
operator
->
()
const
{
}
else
if
(
rhs
.
has_value
())
{
return
std
::
addressof
(
this
->
m_value
);
new
(
std
::
addressof
(
this
->
m_value
))
T
(
std
::
move
(
rhs
.
m_value
));
}
rhs
.
m_value
.
T
::~
T
();
}
TL_OPTIONAL_11_CONSTEXPR
T
*
operator
->
()
{
swap
(
this
->
m_has_value
,
rhs
.
m_has_value
);
return
std
::
addressof
(
this
->
m_value
);
}
}
/// Returns a pointer to the stored value
/// Returns the stored value
constexpr
const
T
*
operator
->
()
const
{
TL_OPTIONAL_11_CONSTEXPR
T
&
operator
*
()
&
{
return
this
->
m_value
;
}
return
std
::
addressof
(
this
->
m_value
);
}
constexpr
const
T
&
operator
*
()
const
&
{
return
this
->
m_value
;
}
TL_OPTIONAL_11_CONSTEXPR
T
*
operator
->
()
{
TL_OPTIONAL_11_CONSTEXPR
T
&&
operator
*
()
&&
{
return
std
::
addressof
(
this
->
m_value
);
return
std
::
move
(
this
->
m_value
);
}
}
/// Returns the stored value
TL_OPTIONAL_11_CONSTEXPR
T
&
operator
*
()
&
{
return
this
->
m_value
;
}
constexpr
const
T
&
operator
*
()
const
&
{
return
this
->
m_value
;
}
TL_OPTIONAL_11_CONSTEXPR
T
&&
operator
*
()
&&
{
return
std
::
move
(
this
->
m_value
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#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
#endif
/// Returns whether or not the optional has a value
/// Returns whether or not the optional has a value
constexpr
bool
has_value
()
const
noexcept
{
return
this
->
m_has_value
;
}
constexpr
bool
has_value
()
const
noexcept
{
return
this
->
m_has_value
;
}
constexpr
explicit
operator
bool
()
const
noexcept
{
constexpr
explicit
operator
bool
()
const
noexcept
{
return
this
->
m_has_value
;
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
TL_OPTIONAL_11_CONSTEXPR
T
&
value
()
&
{
/// bad_optional_access
if
(
has_value
())
TL_OPTIONAL_11_CONSTEXPR
T
&
value
()
&
{
return
this
->
m_value
;
if
(
has_value
())
return
this
->
m_value
;
throw
bad_optional_access
();
throw
bad_optional_access
();
}
}
TL_OPTIONAL_11_CONSTEXPR
const
T
&
value
()
const
&
{
TL_OPTIONAL_11_CONSTEXPR
const
T
&
value
()
const
&
{
if
(
has_value
())
if
(
has_value
())
return
this
->
m_value
;
return
this
->
m_value
;
throw
bad_optional_access
();
throw
bad_optional_access
();
}
}
TL_OPTIONAL_11_CONSTEXPR
T
&&
value
()
&&
{
TL_OPTIONAL_11_CONSTEXPR
T
&&
value
()
&&
{
if
(
has_value
())
return
std
::
move
(
this
->
m_value
);
if
(
has_value
())
throw
bad_optional_access
();
return
std
::
move
(
this
->
m_value
);
}
throw
bad_optional_access
();
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
TL_OPTIONAL_11_CONSTEXPR
const
T
&&
value
()
const
&&
{
TL_OPTIONAL_11_CONSTEXPR
const
T
&&
value
()
const
&&
{
if
(
has_value
())
if
(
has_value
())
return
std
::
move
(
this
->
m_value
);
return
std
::
move
(
this
->
m_value
);
throw
bad_optional_access
();
throw
bad_optional_access
();
}
}
#endif
#endif
/// Returns the stored value if there is one, otherwise returns `u`
/// Returns the stored value if there is one, otherwise returns `u`
template
<
class
U
>
constexpr
T
value_or
(
U
&&
u
)
const
&
{
template
<
class
U
>
static_assert
(
std
::
is_copy_constructible
<
T
>::
value
&&
constexpr
T
value_or
(
U
&&
u
)
const
&
{
std
::
is_convertible
<
U
&&
,
T
>::
value
,
static_assert
(
std
::
is_copy_constructible
<
T
>::
value
&&
"T must be copy constructible and convertible from U"
);
std
::
is_convertible
<
U
&&
,
T
>::
value
,
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
U
>
(
u
));
"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
)
&&
{
static_assert
(
std
::
is_move_constructible
<
T
>::
value
&&
template
<
class
U
>
std
::
is_convertible
<
U
&&
,
T
>::
value
,
TL_OPTIONAL_11_CONSTEXPR
T
value_or
(
U
&&
u
)
&&
{
"T must be move constructible and convertible from U"
);
static_assert
(
std
::
is_move_constructible
<
T
>::
value
&&
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
U
>
(
u
));
std
::
is_convertible
<
U
&&
,
T
>::
value
,
}
"T must be move constructible and convertible from U"
);
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
U
>
(
u
));
/// Destroys the stored value if one exists, making the optional empty
}
void
reset
()
noexcept
{
if
(
has_value
())
{
/// Destroys the stored value if one exists, making the optional empty
this
->
m_value
.
~
T
();
void
reset
()
noexcept
{
this
->
m_has_value
=
false
;
if
(
has_value
())
{
}
this
->
m_value
.
~
T
();
}
this
->
m_has_value
=
false
;
};
// namespace tl
}
}
};
// namespace tl
/// Compares two optional objects
/// Compares two optional objects
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
==
(
const
optional
<
T
>
&
lhs
,
inline
constexpr
bool
operator
==
(
const
optional
<
T
>
&
lhs
,
const
optional
<
U
>
&
rhs
)
{
const
optional
<
U
>
&
rhs
)
{
return
lhs
.
has_value
()
==
rhs
.
has_value
()
&&
return
lhs
.
has_value
()
==
rhs
.
has_value
()
&&
(
!
lhs
.
has_value
()
||
*
lhs
==
*
rhs
);
(
!
lhs
.
has_value
()
||
*
lhs
==
*
rhs
);
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
!=
(
const
optional
<
T
>
&
lhs
,
inline
constexpr
bool
operator
!=
(
const
optional
<
T
>
&
lhs
,
const
optional
<
U
>
&
rhs
)
{
const
optional
<
U
>
&
rhs
)
{
return
lhs
.
has_value
()
!=
rhs
.
has_value
()
||
return
lhs
.
has_value
()
!=
rhs
.
has_value
()
||
(
lhs
.
has_value
()
&&
*
lhs
!=
*
rhs
);
(
lhs
.
has_value
()
&&
*
lhs
!=
*
rhs
);
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
<
(
const
optional
<
T
>
&
lhs
,
inline
constexpr
bool
operator
<
(
const
optional
<
T
>
&
lhs
,
const
optional
<
U
>
&
rhs
)
{
const
optional
<
U
>
&
rhs
)
{
return
rhs
.
has_value
()
&&
(
!
lhs
.
has_value
()
||
*
lhs
<
*
rhs
);
return
rhs
.
has_value
()
&&
(
!
lhs
.
has_value
()
||
*
lhs
<
*
rhs
);
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
>
(
const
optional
<
T
>
&
lhs
,
inline
constexpr
bool
operator
>
(
const
optional
<
T
>
&
lhs
,
const
optional
<
U
>
&
rhs
)
{
const
optional
<
U
>
&
rhs
)
{
return
lhs
.
has_value
()
&&
(
!
rhs
.
has_value
()
||
*
lhs
>
*
rhs
);
return
lhs
.
has_value
()
&&
(
!
rhs
.
has_value
()
||
*
lhs
>
*
rhs
);
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
<=
(
const
optional
<
T
>
&
lhs
,
inline
constexpr
bool
operator
<=
(
const
optional
<
T
>
&
lhs
,
const
optional
<
U
>
&
rhs
)
{
const
optional
<
U
>
&
rhs
)
{
return
!
lhs
.
has_value
()
||
(
rhs
.
has_value
()
&&
*
lhs
<=
*
rhs
);
return
!
lhs
.
has_value
()
||
(
rhs
.
has_value
()
&&
*
lhs
<=
*
rhs
);
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
>=
(
const
optional
<
T
>
&
lhs
,
inline
constexpr
bool
operator
>=
(
const
optional
<
T
>
&
lhs
,
const
optional
<
U
>
&
rhs
)
{
const
optional
<
U
>
&
rhs
)
{
return
!
rhs
.
has_value
()
||
(
lhs
.
has_value
()
&&
*
lhs
>=
*
rhs
);
return
!
rhs
.
has_value
()
||
(
lhs
.
has_value
()
&&
*
lhs
>=
*
rhs
);
}
}
/// Compares an optional to a `nullopt`
/// Compares an optional to a `nullopt`
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
==
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
inline
constexpr
bool
operator
==
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
return
!
lhs
.
has_value
();
return
!
lhs
.
has_value
();
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
==
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
inline
constexpr
bool
operator
==
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
return
!
rhs
.
has_value
();
return
!
rhs
.
has_value
();
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
!=
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
inline
constexpr
bool
operator
!=
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
return
lhs
.
has_value
();
return
lhs
.
has_value
();
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
!=
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
inline
constexpr
bool
operator
!=
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
return
rhs
.
has_value
();
return
rhs
.
has_value
();
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
<
(
const
optional
<
T
>
&
,
nullopt_t
)
noexcept
{
inline
constexpr
bool
operator
<
(
const
optional
<
T
>
&
,
nullopt_t
)
noexcept
{
return
false
;
return
false
;
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
<
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
inline
constexpr
bool
operator
<
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
return
rhs
.
has_value
();
return
rhs
.
has_value
();
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
<=
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
inline
constexpr
bool
operator
<=
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
return
!
lhs
.
has_value
();
return
!
lhs
.
has_value
();
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
<=
(
nullopt_t
,
const
optional
<
T
>
&
)
noexcept
{
inline
constexpr
bool
operator
<=
(
nullopt_t
,
const
optional
<
T
>
&
)
noexcept
{
return
true
;
return
true
;
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
>
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
inline
constexpr
bool
operator
>
(
const
optional
<
T
>
&
lhs
,
nullopt_t
)
noexcept
{
return
lhs
.
has_value
();
return
lhs
.
has_value
();
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
>
(
nullopt_t
,
const
optional
<
T
>
&
)
noexcept
{
inline
constexpr
bool
operator
>
(
nullopt_t
,
const
optional
<
T
>
&
)
noexcept
{
return
false
;
return
false
;
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
>=
(
const
optional
<
T
>
&
,
nullopt_t
)
noexcept
{
inline
constexpr
bool
operator
>=
(
const
optional
<
T
>
&
,
nullopt_t
)
noexcept
{
return
true
;
return
true
;
}
}
template
<
class
T
>
template
<
class
T
>
inline
constexpr
bool
operator
>=
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
inline
constexpr
bool
operator
>=
(
nullopt_t
,
const
optional
<
T
>
&
rhs
)
noexcept
{
return
!
rhs
.
has_value
();
return
!
rhs
.
has_value
();
}
}
/// Compares the optional with a value.
/// Compares the optional with a value.
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
==
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
inline
constexpr
bool
operator
==
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
return
lhs
.
has_value
()
?
*
lhs
==
rhs
:
false
;
return
lhs
.
has_value
()
?
*
lhs
==
rhs
:
false
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
==
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
inline
constexpr
bool
operator
==
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
return
rhs
.
has_value
()
?
lhs
==
*
rhs
:
false
;
return
rhs
.
has_value
()
?
lhs
==
*
rhs
:
false
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
!=
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
inline
constexpr
bool
operator
!=
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
return
lhs
.
has_value
()
?
*
lhs
!=
rhs
:
true
;
return
lhs
.
has_value
()
?
*
lhs
!=
rhs
:
true
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
!=
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
inline
constexpr
bool
operator
!=
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
return
rhs
.
has_value
()
?
lhs
!=
*
rhs
:
true
;
return
rhs
.
has_value
()
?
lhs
!=
*
rhs
:
true
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
<
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
inline
constexpr
bool
operator
<
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
return
lhs
.
has_value
()
?
*
lhs
<
rhs
:
true
;
return
lhs
.
has_value
()
?
*
lhs
<
rhs
:
true
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
<
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
inline
constexpr
bool
operator
<
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
return
rhs
.
has_value
()
?
lhs
<
*
rhs
:
false
;
return
rhs
.
has_value
()
?
lhs
<
*
rhs
:
false
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
<=
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
inline
constexpr
bool
operator
<=
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
return
lhs
.
has_value
()
?
*
lhs
<=
rhs
:
true
;
return
lhs
.
has_value
()
?
*
lhs
<=
rhs
:
true
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
<=
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
inline
constexpr
bool
operator
<=
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
return
rhs
.
has_value
()
?
lhs
<=
*
rhs
:
false
;
return
rhs
.
has_value
()
?
lhs
<=
*
rhs
:
false
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
>
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
inline
constexpr
bool
operator
>
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
return
lhs
.
has_value
()
?
*
lhs
>
rhs
:
false
;
return
lhs
.
has_value
()
?
*
lhs
>
rhs
:
false
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
>
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
inline
constexpr
bool
operator
>
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
return
rhs
.
has_value
()
?
lhs
>
*
rhs
:
true
;
return
rhs
.
has_value
()
?
lhs
>
*
rhs
:
true
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
>=
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
inline
constexpr
bool
operator
>=
(
const
optional
<
T
>
&
lhs
,
const
U
&
rhs
)
{
return
lhs
.
has_value
()
?
*
lhs
>=
rhs
:
false
;
return
lhs
.
has_value
()
?
*
lhs
>=
rhs
:
false
;
}
}
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
inline
constexpr
bool
operator
>=
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
inline
constexpr
bool
operator
>=
(
const
U
&
lhs
,
const
optional
<
T
>
&
rhs
)
{
return
rhs
.
has_value
()
?
lhs
>=
*
rhs
:
true
;
return
rhs
.
has_value
()
?
lhs
>=
*
rhs
:
true
;
}
}
template
<
class
T
,
template
<
class
T
,
...
@@ -1475,590 +1564,619 @@ template <class T,
...
@@ -1475,590 +1564,619 @@ template <class T,
detail
::
enable_if_t
<
detail
::
is_swappable
<
T
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<
detail
::
is_swappable
<
T
>::
value
>
*
=
nullptr
>
void
swap
(
optional
<
T
>
&
lhs
,
void
swap
(
optional
<
T
>
&
lhs
,
optional
<
T
>
&
rhs
)
noexcept
(
noexcept
(
lhs
.
swap
(
rhs
)))
{
optional
<
T
>
&
rhs
)
noexcept
(
noexcept
(
lhs
.
swap
(
rhs
)))
{
return
lhs
.
swap
(
rhs
);
return
lhs
.
swap
(
rhs
);
}
}
namespace
detail
{
namespace
detail
{
struct
i_am_secret
{};
struct
i_am_secret
{};
}
// namespace detail
}
// namespace detail
template
<
class
T
=
detail
::
i_am_secret
,
class
U
,
template
<
class
T
=
detail
::
i_am_secret
,
class
U
,
class
Ret
=
class
Ret
=
detail
::
conditional_t
<
std
::
is_same
<
T
,
detail
::
i_am_secret
>
::
value
,
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
)
{
inline
constexpr
optional
<
Ret
>
make_optional
(
U
&&
v
)
{
return
optional
<
Ret
>
(
std
::
forward
<
U
>
(
v
));
return
optional
<
Ret
>
(
std
::
forward
<
U
>
(
v
));
}
}
template
<
class
T
,
class
...
Args
>
template
<
class
T
,
class
...
Args
>
inline
constexpr
optional
<
T
>
make_optional
(
Args
&&
...
args
)
{
inline
constexpr
optional
<
T
>
make_optional
(
Args
&&
...
args
)
{
return
optional
<
T
>
(
in_place
,
std
::
forward
<
Args
>
(
args
)...);
return
optional
<
T
>
(
in_place
,
std
::
forward
<
Args
>
(
args
)...);
}
}
template
<
class
T
,
class
U
,
class
...
Args
>
template
<
class
T
,
class
U
,
class
...
Args
>
inline
constexpr
optional
<
T
>
make_optional
(
std
::
initializer_list
<
U
>
il
,
inline
constexpr
optional
<
T
>
make_optional
(
std
::
initializer_list
<
U
>
il
,
Args
&&
...
args
)
{
Args
&&
...
args
)
{
return
optional
<
T
>
(
in_place
,
il
,
std
::
forward
<
Args
>
(
args
)...);
return
optional
<
T
>
(
in_place
,
il
,
std
::
forward
<
Args
>
(
args
)...);
}
}
#if __cplusplus >= 201703L
#if __cplusplus >= 201703L
template
<
class
T
>
optional
(
T
)
->
optional
<
T
>
;
template
<
class
T
>
optional
(
T
)
->
optional
<
T
>
;
#endif
#endif
/// \exclude
/// \exclude
namespace
detail
{
namespace
detail
{
#ifdef TL_OPTIONAL_CXX14
#ifdef TL_OPTIONAL_CXX14
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<!
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<!
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
constexpr
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
{
constexpr
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
{
return
opt
.
has_value
()
return
opt
.
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
))
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
))
:
optional
<
Ret
>
(
nullopt
);
:
optional
<
Ret
>
(
nullopt
);
}
}
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
{
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
{
if
(
opt
.
has_value
())
{
if
(
opt
.
has_value
())
{
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
));
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
));
return
make_optional
(
monostate
{});
return
make_optional
(
monostate
{});
}
}
return
optional
<
monostate
>
(
nullopt
);
return
optional
<
monostate
>
(
nullopt
);
}
}
#else
#else
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<!
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<!
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
constexpr
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
->
optional
<
Ret
>
{
constexpr
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
->
optional
<
Ret
>
{
return
opt
.
has_value
()
return
opt
.
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
))
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
))
:
optional
<
Ret
>
(
nullopt
);
:
optional
<
Ret
>
(
nullopt
);
}
}
template
<
class
Opt
,
class
F
,
template
<
class
Opt
,
class
F
,
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
class
Ret
=
decltype
(
detail
::
invoke
(
std
::
declval
<
F
>(),
*
std
::
declval
<
Opt
>
())),
*
std
::
declval
<
Opt
>
())),
detail
::
enable_if_t
<
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
detail
::
enable_if_t
<
std
::
is_void
<
Ret
>::
value
>
*
=
nullptr
>
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
->
optional
<
monostate
>
{
auto
optional_map_impl
(
Opt
&&
opt
,
F
&&
f
)
->
optional
<
monostate
>
{
if
(
opt
.
has_value
())
{
if
(
opt
.
has_value
())
{
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
));
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
*
std
::
forward
<
Opt
>
(
opt
));
return
monostate
{};
return
monostate
{};
}
}
return
nullopt
;
return
nullopt
;
}
}
#endif
#endif
}
// namespace detail
}
// namespace detail
/// Specialization for when `T` is a reference. `optional<T&>` acts similarly
/// Specialization for when `T` is a reference. `optional<T&>` acts similarly
/// to a `T*`, but provides more operations and shows intent more clearly.
/// to a `T*`, but provides more operations and shows intent more clearly.
template
<
class
T
>
class
optional
<
T
&>
{
template
<
class
T
>
public:
class
optional
<
T
&>
{
public:
// The different versions for C++14 and 11 are needed because deduced return
// 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
// types are not SFINAE-safe. This provides better support for things like
// generic lambdas. C.f.
// generic lambdas. C.f.
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&
\
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation which returns an optional on the stored
/// Carries out some operation which returns an optional on the stored
/// object if there is one.
/// object if there is one.
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
template
<
class
F
>
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
:
result
(
nullopt
);
}
}
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
template
<
class
F
>
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
TL_OPTIONAL_11_CONSTEXPR
auto
and_then
(
F
&&
f
)
&&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
:
result
(
nullopt
);
}
}
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
template
<
class
F
>
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
constexpr
auto
and_then
(
F
&&
f
)
const
&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
:
result
(
nullopt
);
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
template
<
class
F
>
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
constexpr
auto
and_then
(
F
&&
f
)
const
&&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
result
(
nullopt
);
}
#endif
#endif
#else
#else
/// Carries out some operation which returns an optional on the stored
/// Carries out some operation which returns an optional on the stored
/// object if there is one.
/// object if there is one.
template
<
class
F
>
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
&>
;
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
:
result
(
nullopt
);
}
}
template
<
class
F
>
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
(
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
F
&&
f
)
&&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
T
&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
result
(
nullopt
);
}
template
<
class
F
>
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&>
and_then
(
F
&&
f
)
const
&
{
template
<
class
F
>
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&>
and_then
(
F
&&
f
)
const
&
{
static_assert
(
detail
::
is_optional
<
result
>::
value
,
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
"F must return an optional"
);
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
result
(
nullopt
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
template
<
class
F
>
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&>
and_then
(
F
&&
f
)
const
&&
{
constexpr
detail
::
invoke_result_t
<
F
,
const
T
&>
and_then
(
F
&&
f
)
const
&&
{
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
using
result
=
detail
::
invoke_result_t
<
F
,
const
T
&>
;
static_assert
(
detail
::
is_optional
<
result
>::
value
,
static_assert
(
detail
::
is_optional
<
result
>::
value
,
"F must return an optional"
);
"F must return an optional"
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
result
(
nullopt
);
:
result
(
nullopt
);
}
}
#endif
#endif
#endif
#endif
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&
\
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
/// 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
>
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
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
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
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
&
{
}
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
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
constexpr
auto
map
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
#else
/// Carries out some operation on the stored object if there is one.
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&
{
map
(
F
&&
f
)
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
&&
{
map
(
F
&&
f
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
const
&
{
map
(
F
&&
f
)
const
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
map
(
F
&&
f
)
const
&&
{
map
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
#endif
#endif
#endif
#endif
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&
\
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
!defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
/// Carries out some operation on the stored object if there is one.
/// 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
>
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
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
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
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
&
{
}
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
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
constexpr
auto
transform
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
#else
#else
/// Carries out some operation on the stored object if there is one.
/// Carries out some operation on the stored object if there is one.
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&
{
transform
(
F
&&
f
)
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
/// \group map
/// \group map
/// \synopsis template <class F> auto transform(F &&f) &&;
/// \synopsis template <class F> auto transform(F &&f) &&;
template
<
class
F
>
template
<
class
F
>
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
optional
&&>
(),
TL_OPTIONAL_11_CONSTEXPR
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
&&
{
transform
(
F
&&
f
)
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&>
(),
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
const
optional
&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&
{
transform
(
F
&&
f
)
const
&
{
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
*
this
,
std
::
forward
<
F
>
(
f
));
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
>
template
<
class
F
>
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
const
optional
&&>
(),
constexpr
decltype
(
detail
::
optional_map_impl
(
std
::
declval
<
F
&&>
()))
std
::
declval
<
const
optional
&&>
(),
std
::
declval
<
F
&&>
()))
transform
(
F
&&
f
)
const
&&
{
transform
(
F
&&
f
)
const
&&
{
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
return
detail
::
optional_map_impl
(
std
::
move
(
*
this
),
std
::
forward
<
F
>
(
f
));
}
}
#endif
#endif
#endif
#endif
/// Calls `f` if the optional is empty
/// Calls `f` if the optional is empty
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
if
(
has_value
())
if
(
has_value
())
return
*
this
;
return
*
this
;
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&
{
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
}
}
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
&&
{
optional
<
T
>
or_else
(
F
&&
f
)
&&
{
if
(
has_value
())
if
(
has_value
())
return
std
::
move
(
*
this
);
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
}
}
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&
{
optional
<
T
>
or_else
(
F
&&
f
)
const
&
{
if
(
has_value
())
if
(
has_value
())
return
*
this
;
return
*
this
;
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
const
&
{
optional
<
T
>
TL_OPTIONAL_11_CONSTEXPR
or_else
(
F
&&
f
)
const
&
{
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
*
this
:
std
::
forward
<
F
>
(
f
)();
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
enable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
if
(
has_value
())
if
(
has_value
())
return
std
::
move
(
*
this
);
return
std
::
move
(
*
this
);
std
::
forward
<
F
>
(
f
)();
std
::
forward
<
F
>
(
f
)();
return
nullopt
;
return
nullopt
;
}
}
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
template
<
class
F
,
detail
::
disable_if_ret_void
<
F
>
*
=
nullptr
>
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
optional
<
T
>
or_else
(
F
&&
f
)
const
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
forward
<
F
>
(
f
)();
}
}
#endif
#endif
/// Maps the stored value with `f` if there is one, otherwise returns `u`
/// 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
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
U
map_or
(
F
&&
f
,
U
&&
u
)
&
{
:
std
::
forward
<
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
)
&&
{
template
<
class
F
,
class
U
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
U
map_or
(
F
&&
f
,
U
&&
u
)
&&
{
:
std
::
forward
<
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
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&
{
:
std
::
forward
<
U
>
(
u
);
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
std
::
forward
<
U
>
(
u
);
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
template
<
class
F
,
class
U
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
U
map_or
(
F
&&
f
,
U
&&
u
)
const
&&
{
:
std
::
forward
<
U
>
(
u
);
return
has_value
()
}
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
:
std
::
forward
<
U
>
(
u
);
}
#endif
#endif
/// Maps the stored value with `f` if there is one, otherwise calls
/// Maps the stored value with `f` if there is one, otherwise calls
/// `u` and returns the result.
/// `u` and returns the result.
template
<
class
F
,
class
U
>
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
&
{
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
&
{
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
:
std
::
forward
<
U
>
(
u
)();
:
std
::
forward
<
U
>
(
u
)();
}
}
template
<
class
F
,
class
U
>
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
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
()
:
std
::
forward
<
U
>
(
u
)();
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
}
:
std
::
forward
<
U
>
(
u
)();
}
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&
{
template
<
class
F
,
class
U
>
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&
{
:
std
::
forward
<
U
>
(
u
)();
return
has_value
()
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
**
this
)
}
:
std
::
forward
<
U
>
(
u
)();
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
template
<
class
F
,
class
U
>
template
<
class
F
,
class
U
>
detail
::
invoke_result_t
<
U
>
map_or_else
(
F
&&
f
,
U
&&
u
)
const
&&
{
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
()
:
std
::
forward
<
U
>
(
u
)();
?
detail
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
**
this
))
}
:
std
::
forward
<
U
>
(
u
)();
}
#endif
#endif
/// Returns `u` if `*this` has a value, otherwise an empty optional.
/// Returns `u` if `*this` has a value, otherwise an empty optional.
template
<
class
U
>
template
<
class
U
>
constexpr
optional
<
typename
std
::
decay
<
U
>::
type
>
conjunction
(
U
&&
u
)
const
{
constexpr
optional
<
typename
std
::
decay
<
U
>::
type
>
conjunction
(
U
&&
u
)
const
{
using
result
=
optional
<
detail
::
decay_t
<
U
>>
;
using
result
=
optional
<
detail
::
decay_t
<
U
>>
;
return
has_value
()
?
result
{
u
}
:
result
{
nullopt
};
return
has_value
()
?
result
{
u
}
:
result
{
nullopt
};
}
}
/// Returns `rhs` if `*this` is empty, otherwise the current value.
/// Returns `rhs` if `*this` is empty, otherwise the current value.
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&
{
return
has_value
()
?
*
this
:
rhs
;
return
has_value
()
?
*
this
:
rhs
;
}
}
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&
{
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&
{
return
has_value
()
?
*
this
:
rhs
;
return
has_value
()
?
*
this
:
rhs
;
}
}
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
const
optional
&
rhs
)
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&&
{
constexpr
optional
disjunction
(
const
optional
&
rhs
)
const
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
return
has_value
()
?
std
::
move
(
*
this
)
:
rhs
;
}
}
#endif
#endif
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&
{
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
}
}
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&
{
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&
{
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
return
has_value
()
?
*
this
:
std
::
move
(
rhs
);
}
}
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&&
{
TL_OPTIONAL_11_CONSTEXPR
optional
disjunction
(
optional
&&
rhs
)
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
}
}
#ifndef TL_OPTIONAL_NO_CONSTRR
#ifndef TL_OPTIONAL_NO_CONSTRR
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&&
{
constexpr
optional
disjunction
(
optional
&&
rhs
)
const
&&
{
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
return
has_value
()
?
std
::
move
(
*
this
)
:
std
::
move
(
rhs
);
}
}
#endif
#endif
/// Takes the value out of the optional, leaving it empty
/// Takes the value out of the optional, leaving it empty
optional
take
()
{
optional
take
()
{
optional
ret
=
std
::
move
(
*
this
);
optional
ret
=
std
::
move
(
*
this
);
reset
();
reset
();
return
ret
;
return
ret
;
}
}
using
value_type
=
T
&
;
using
value_type
=
T
&
;
/// Constructs an optional that does not contain a value.
/// Constructs an optional that does not contain a value.
constexpr
optional
()
noexcept
:
m_value
(
nullptr
)
{}
constexpr
optional
()
noexcept
:
m_value
(
nullptr
)
{}
constexpr
optional
(
nullopt_t
)
noexcept
:
m_value
(
nullptr
)
{}
constexpr
optional
(
nullopt_t
)
noexcept
:
m_value
(
nullptr
)
{}
/// Copy constructor
/// Copy constructor
///
///
/// If `rhs` contains a value, the stored value is direct-initialized with
/// If `rhs` contains a value, the stored value is direct-initialized with
/// it. Otherwise, the constructed optional is empty.
/// it. Otherwise, the constructed optional is empty.
TL_OPTIONAL_11_CONSTEXPR
optional
(
const
optional
&
rhs
)
noexcept
=
default
;
TL_OPTIONAL_11_CONSTEXPR
optional
(
const
optional
&
rhs
)
noexcept
=
default
;
/// Move constructor
/// Move constructor
///
///
/// If `rhs` contains a value, the stored value is direct-initialized with
/// If `rhs` contains a value, the stored value is direct-initialized with
/// it. Otherwise, the constructed optional is empty.
/// it. Otherwise, the constructed optional is empty.
TL_OPTIONAL_11_CONSTEXPR
optional
(
optional
&&
rhs
)
=
default
;
TL_OPTIONAL_11_CONSTEXPR
optional
(
optional
&&
rhs
)
=
default
;
/// Constructs the stored value with `u`.
/// Constructs the stored value with `u`.
template
<
class
U
=
T
,
template
<
class
U
=
T
,
detail
::
enable_if_t
<!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
detail
::
enable_if_t
<
*
=
nullptr
>
!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
constexpr
optional
(
U
&&
u
)
noexcept
:
m_value
(
std
::
addressof
(
u
))
{
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
)
{}
template
<
class
U
>
constexpr
explicit
optional
(
const
optional
<
U
>
&
rhs
)
noexcept
/// No-op
:
optional
(
*
rhs
)
{}
~
optional
()
=
default
;
/// No-op
/// Assignment to empty.
~
optional
()
=
default
;
///
/// Destroys the current value if there is one.
/// Assignment to empty.
optional
&
operator
=
(
nullopt_t
)
noexcept
{
///
m_value
=
nullptr
;
/// Destroys the current value if there is one.
return
*
this
;
optional
&
operator
=
(
nullopt_t
)
noexcept
{
}
m_value
=
nullptr
;
return
*
this
;
/// Copy assignment.
}
///
/// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
/// Copy assignment.
/// resets the stored value in `*this`.
///
optional
&
operator
=
(
const
optional
&
rhs
)
=
default
;
/// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
/// resets the stored value in `*this`.
/// Rebinds this optional to `u`.
optional
&
operator
=
(
const
optional
&
rhs
)
=
default
;
template
<
class
U
=
T
,
detail
::
enable_if_t
<!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
/// Rebinds this optional to `u`.
*
=
nullptr
>
template
<
class
U
=
T
,
optional
&
operator
=
(
U
&&
u
)
{
detail
::
enable_if_t
<
static_assert
(
std
::
is_lvalue_reference
<
U
>::
value
,
"U must be an lvalue"
);
!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
m_value
=
std
::
addressof
(
u
);
optional
&
operator
=
(
U
&&
u
)
{
return
*
this
;
static_assert
(
std
::
is_lvalue_reference
<
U
>::
value
,
}
"U must be an lvalue"
);
m_value
=
std
::
addressof
(
u
);
/// Converting copy assignment operator.
return
*
this
;
///
}
/// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
/// resets the stored value in `*this`.
/// Converting copy assignment operator.
template
<
class
U
>
optional
&
operator
=
(
const
optional
<
U
>
&
rhs
)
noexcept
{
///
m_value
=
std
::
addressof
(
rhs
.
value
());
/// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
return
*
this
;
/// resets the stored value in `*this`.
}
template
<
class
U
>
optional
&
operator
=
(
const
optional
<
U
>
&
rhs
)
noexcept
{
/// Rebinds this optional to `u`.
m_value
=
std
::
addressof
(
rhs
.
value
());
template
<
class
U
=
T
,
return
*
this
;
detail
::
enable_if_t
<!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
}
*
=
nullptr
>
optional
&
emplace
(
U
&&
u
)
noexcept
{
/// Rebinds this optional to `u`.
return
*
this
=
std
::
forward
<
U
>
(
u
);
template
<
class
U
=
T
,
}
detail
::
enable_if_t
<
!
detail
::
is_optional
<
detail
::
decay_t
<
U
>
>::
value
>
*
=
nullptr
>
void
swap
(
optional
&
rhs
)
noexcept
{
std
::
swap
(
m_value
,
rhs
.
m_value
);
}
optional
&
emplace
(
U
&&
u
)
noexcept
{
return
*
this
=
std
::
forward
<
U
>
(
u
);
/// Returns a pointer to the stored value
}
constexpr
const
T
*
operator
->
()
const
noexcept
{
return
m_value
;
}
void
swap
(
optional
&
rhs
)
noexcept
{
std
::
swap
(
m_value
,
rhs
.
m_value
);
}
TL_OPTIONAL_11_CONSTEXPR
T
*
operator
->
()
noexcept
{
return
m_value
;
}
/// Returns a pointer to the stored value
/// Returns the stored value
constexpr
const
T
*
operator
->
()
const
noexcept
{
return
m_value
;
}
TL_OPTIONAL_11_CONSTEXPR
T
&
operator
*
()
noexcept
{
return
*
m_value
;
}
TL_OPTIONAL_11_CONSTEXPR
T
*
operator
->
()
noexcept
{
return
m_value
;
}
constexpr
const
T
&
operator
*
()
const
noexcept
{
return
*
m_value
;
}
/// Returns the stored value
constexpr
bool
has_value
()
const
noexcept
{
return
m_value
!=
nullptr
;
}
TL_OPTIONAL_11_CONSTEXPR
T
&
operator
*
()
noexcept
{
return
*
m_value
;
}
constexpr
explicit
operator
bool
()
const
noexcept
{
constexpr
const
T
&
operator
*
()
const
noexcept
{
return
*
m_value
;
}
return
m_value
!=
nullptr
;
}
constexpr
bool
has_value
()
const
noexcept
{
return
m_value
!=
nullptr
;
}
/// Returns the contained value if there is one, otherwise throws bad_optional_access
constexpr
explicit
operator
bool
()
const
noexcept
{
TL_OPTIONAL_11_CONSTEXPR
T
&
value
()
{
return
m_value
!=
nullptr
;
if
(
has_value
())
}
return
*
m_value
;
throw
bad_optional_access
();
/// Returns the contained value if there is one, otherwise throws
}
/// bad_optional_access
TL_OPTIONAL_11_CONSTEXPR
const
T
&
value
()
const
{
TL_OPTIONAL_11_CONSTEXPR
T
&
value
()
{
if
(
has_value
())
if
(
has_value
())
return
*
m_value
;
return
*
m_value
;
throw
bad_optional_access
();
throw
bad_optional_access
();
}
}
TL_OPTIONAL_11_CONSTEXPR
const
T
&
value
()
const
{
if
(
has_value
())
return
*
m_value
;
/// Returns the stored value if there is one, otherwise returns `u`
throw
bad_optional_access
();
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
,
/// Returns the stored value if there is one, otherwise returns `u`
"T must be copy constructible and convertible from U"
);
template
<
class
U
>
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
U
>
(
u
));
constexpr
T
value_or
(
U
&&
u
)
const
&
noexcept
{
}
static_assert
(
std
::
is_copy_constructible
<
T
>::
value
&&
std
::
is_convertible
<
U
&&
,
T
>::
value
,
/// \group value_or
"T must be copy constructible and convertible from U"
);
template
<
class
U
>
TL_OPTIONAL_11_CONSTEXPR
T
value_or
(
U
&&
u
)
&&
noexcept
{
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
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"
);
/// \group value_or
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
U
>
(
u
));
template
<
class
U
>
}
TL_OPTIONAL_11_CONSTEXPR
T
value_or
(
U
&&
u
)
&&
noexcept
{
static_assert
(
std
::
is_move_constructible
<
T
>::
value
&&
/// Destroys the stored value if one exists, making the optional empty
std
::
is_convertible
<
U
&&
,
T
>::
value
,
void
reset
()
noexcept
{
m_value
=
nullptr
;
}
"T must be move constructible and convertible from U"
);
return
has_value
()
?
**
this
:
static_cast
<
T
>
(
std
::
forward
<
U
>
(
u
));
private:
}
T
*
m_value
;
};
// namespace tl
/// Destroys the stored value if one exists, making the optional empty
void
reset
()
noexcept
{
m_value
=
nullptr
;
}
private:
}
// namespace tl
T
*
m_value
;
};
// namespace tl
}
// namespace tl
namespace
std
{
namespace
std
{
// TODO SFINAE
// TODO SFINAE
template
<
class
T
>
struct
hash
<
tl
::
optional
<
T
>>
{
template
<
class
T
>
::
std
::
size_t
operator
()(
const
tl
::
optional
<
T
>
&
o
)
const
{
struct
hash
<
tl
::
optional
<
T
>>
{
if
(
!
o
.
has_value
())
::
std
::
size_t
operator
()(
const
tl
::
optional
<
T
>
&
o
)
const
{
return
0
;
if
(
!
o
.
has_value
())
return
0
;
return
std
::
hash
<
tl
::
detail
::
remove_const_t
<
T
>>
()(
*
o
);
return
std
::
hash
<
tl
::
detail
::
remove_const_t
<
T
>>
()(
*
o
);
}
}
};
};
}
// namespace std
}
// namespace std
#endif
#endif
paddlespeech/audio/src/pybind/kaldi_frontend/feature_common.h
浏览文件 @
a3911ab5
...
@@ -14,9 +14,9 @@
...
@@ -14,9 +14,9 @@
#pragma once
#pragma once
#include "feat/feature-window.h"
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include "feat/feature-window.h"
namespace
paddleaudio
{
namespace
paddleaudio
{
...
@@ -27,18 +27,14 @@ class StreamingFeatureTpl {
...
@@ -27,18 +27,14 @@ class StreamingFeatureTpl {
public:
public:
typedef
typename
F
::
Options
Options
;
typedef
typename
F
::
Options
Options
;
StreamingFeatureTpl
(
const
Options
&
opts
);
StreamingFeatureTpl
(
const
Options
&
opts
);
bool
ComputeFeature
(
const
kaldi
::
VectorBase
<
kaldi
::
BaseFloat
>&
wav
,
bool
ComputeFeature
(
const
kaldi
::
VectorBase
<
kaldi
::
BaseFloat
>&
wav
,
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
);
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
);
void
Reset
()
{
void
Reset
()
{
remained_wav_
.
Resize
(
0
);
}
remained_wav_
.
Resize
(
0
);
}
int
Dim
()
{
int
Dim
()
{
return
computer_
.
Dim
();
}
return
computer_
.
Dim
();
}
private:
private:
bool
Compute
(
const
kaldi
::
Vector
<
kaldi
::
BaseFloat
>&
waves
,
bool
Compute
(
const
kaldi
::
Vector
<
kaldi
::
BaseFloat
>&
waves
,
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
);
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
);
Options
opts_
;
Options
opts_
;
kaldi
::
FeatureWindowFunction
window_function_
;
kaldi
::
FeatureWindowFunction
window_function_
;
...
@@ -49,4 +45,3 @@ class StreamingFeatureTpl {
...
@@ -49,4 +45,3 @@ class StreamingFeatureTpl {
}
// namespace ppspeech
}
// namespace ppspeech
#include "feature_common_inl.h"
#include "feature_common_inl.h"
paddlespeech/audio/src/pybind/kaldi_frontend/feature_common_inl.h
浏览文件 @
a3911ab5
...
@@ -17,16 +17,15 @@
...
@@ -17,16 +17,15 @@
namespace
paddleaudio
{
namespace
paddleaudio
{
template
<
class
F
>
template
<
class
F
>
StreamingFeatureTpl
<
F
>::
StreamingFeatureTpl
(
StreamingFeatureTpl
<
F
>::
StreamingFeatureTpl
(
const
Options
&
opts
)
const
Options
&
opts
)
:
opts_
(
opts
),
computer_
(
opts
),
window_function_
(
opts
.
frame_opts
)
{
:
opts_
(
opts
),
computer_
(
opts
),
// window_function_(computer_.GetFrameOptions()) { the opt set to zero
window_function_
(
opts
.
frame_opts
)
{
//window_function_(computer_.GetFrameOptions()) { the opt set to zero
}
}
template
<
class
F
>
template
<
class
F
>
bool
StreamingFeatureTpl
<
F
>::
ComputeFeature
(
const
kaldi
::
VectorBase
<
kaldi
::
BaseFloat
>&
wav
,
bool
StreamingFeatureTpl
<
F
>::
ComputeFeature
(
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
)
{
const
kaldi
::
VectorBase
<
kaldi
::
BaseFloat
>&
wav
,
kaldi
::
Vector
<
kaldi
::
BaseFloat
>*
feats
)
{
// append remaned waves
// append remaned waves
kaldi
::
int32
wav_len
=
wav
.
Dim
();
kaldi
::
int32
wav_len
=
wav
.
Dim
();
if
(
wav_len
==
0
)
return
false
;
if
(
wav_len
==
0
)
return
false
;
...
@@ -61,7 +60,7 @@ bool StreamingFeatureTpl<F>::Compute(
...
@@ -61,7 +60,7 @@ bool StreamingFeatureTpl<F>::Compute(
kaldi
::
int32
frame_length
=
frame_opts
.
WindowSize
();
kaldi
::
int32
frame_length
=
frame_opts
.
WindowSize
();
kaldi
::
int32
sample_rate
=
frame_opts
.
samp_freq
;
kaldi
::
int32
sample_rate
=
frame_opts
.
samp_freq
;
if
(
num_samples
<
frame_length
)
{
if
(
num_samples
<
frame_length
)
{
return
false
;
return
false
;
}
}
kaldi
::
int32
num_frames
=
kaldi
::
NumFrames
(
num_samples
,
frame_opts
);
kaldi
::
int32
num_frames
=
kaldi
::
NumFrames
(
num_samples
,
frame_opts
);
...
...
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature.cc
浏览文件 @
a3911ab5
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include "kaldi_feature_wrapper.h"
#include "kaldi_feature_wrapper.h"
namespace
py
=
pybind11
;
namespace
py
=
pybind11
;
bool
InitFbank
(
bool
InitFbank
(
float
samp_freq
,
// frame opts
float
samp_freq
,
// frame opts
float
frame_shift_ms
,
float
frame_shift_ms
,
float
frame_length_ms
,
float
frame_length_ms
,
float
dither
,
float
dither
,
float
preemph_coeff
,
float
preemph_coeff
,
bool
remove_dc_offset
,
bool
remove_dc_offset
,
std
::
string
window_type
,
// e.g. Hamming window
std
::
string
window_type
,
// e.g. Hamming window
bool
round_to_power_of_two
,
bool
round_to_power_of_two
,
float
blackman_coeff
,
float
blackman_coeff
,
bool
snip_edges
,
bool
snip_edges
,
bool
allow_downsample
,
bool
allow_downsample
,
bool
allow_upsample
,
bool
allow_upsample
,
int
max_feature_vectors
,
int
max_feature_vectors
,
int
num_bins
,
// mel opts
int
num_bins
,
// mel opts
float
low_freq
,
float
low_freq
,
float
high_freq
,
float
high_freq
,
float
vtln_low
,
float
vtln_low
,
float
vtln_high
,
float
vtln_high
,
bool
debug_mel
,
bool
debug_mel
,
bool
htk_mode
,
bool
htk_mode
,
bool
use_energy
,
// fbank opts
bool
use_energy
,
// fbank opts
float
energy_floor
,
float
energy_floor
,
bool
raw_energy
,
bool
raw_energy
,
bool
htk_compat
,
bool
htk_compat
,
bool
use_log_fbank
,
bool
use_log_fbank
,
bool
use_power
)
{
bool
use_power
)
{
kaldi
::
FbankOptions
opts
;
kaldi
::
FbankOptions
opts
;
opts
.
frame_opts
.
samp_freq
=
samp_freq
;
// frame opts
opts
.
frame_opts
.
samp_freq
=
samp_freq
;
// frame opts
opts
.
frame_opts
.
frame_shift_ms
=
frame_shift_ms
;
opts
.
frame_opts
.
frame_shift_ms
=
frame_shift_ms
;
opts
.
frame_opts
.
frame_length_ms
=
frame_length_ms
;
opts
.
frame_opts
.
frame_length_ms
=
frame_length_ms
;
opts
.
frame_opts
.
dither
=
dither
;
opts
.
frame_opts
.
dither
=
dither
;
opts
.
frame_opts
.
preemph_coeff
=
preemph_coeff
;
opts
.
frame_opts
.
preemph_coeff
=
preemph_coeff
;
opts
.
frame_opts
.
remove_dc_offset
=
remove_dc_offset
;
opts
.
frame_opts
.
remove_dc_offset
=
remove_dc_offset
;
opts
.
frame_opts
.
window_type
=
window_type
;
opts
.
frame_opts
.
window_type
=
window_type
;
opts
.
frame_opts
.
round_to_power_of_two
=
round_to_power_of_two
;
opts
.
frame_opts
.
round_to_power_of_two
=
round_to_power_of_two
;
opts
.
frame_opts
.
blackman_coeff
=
blackman_coeff
;
opts
.
frame_opts
.
blackman_coeff
=
blackman_coeff
;
opts
.
frame_opts
.
snip_edges
=
snip_edges
;
opts
.
frame_opts
.
snip_edges
=
snip_edges
;
...
@@ -48,7 +47,7 @@ bool InitFbank(
...
@@ -48,7 +47,7 @@ bool InitFbank(
opts
.
frame_opts
.
allow_upsample
=
allow_upsample
;
opts
.
frame_opts
.
allow_upsample
=
allow_upsample
;
opts
.
frame_opts
.
max_feature_vectors
=
max_feature_vectors
;
opts
.
frame_opts
.
max_feature_vectors
=
max_feature_vectors
;
opts
.
mel_opts
.
num_bins
=
num_bins
;
// mel opts
opts
.
mel_opts
.
num_bins
=
num_bins
;
// mel opts
opts
.
mel_opts
.
low_freq
=
low_freq
;
opts
.
mel_opts
.
low_freq
=
low_freq
;
opts
.
mel_opts
.
high_freq
=
high_freq
;
opts
.
mel_opts
.
high_freq
=
high_freq
;
opts
.
mel_opts
.
vtln_low
=
vtln_low
;
opts
.
mel_opts
.
vtln_low
=
vtln_low
;
...
@@ -56,7 +55,7 @@ bool InitFbank(
...
@@ -56,7 +55,7 @@ bool InitFbank(
opts
.
mel_opts
.
debug_mel
=
debug_mel
;
opts
.
mel_opts
.
debug_mel
=
debug_mel
;
opts
.
mel_opts
.
htk_mode
=
htk_mode
;
opts
.
mel_opts
.
htk_mode
=
htk_mode
;
opts
.
use_energy
=
use_energy
;
// fbank opts
opts
.
use_energy
=
use_energy
;
// fbank opts
opts
.
energy_floor
=
energy_floor
;
opts
.
energy_floor
=
energy_floor
;
opts
.
raw_energy
=
raw_energy
;
opts
.
raw_energy
=
raw_energy
;
opts
.
htk_compat
=
htk_compat
;
opts
.
htk_compat
=
htk_compat
;
...
@@ -67,71 +66,71 @@ bool InitFbank(
...
@@ -67,71 +66,71 @@ bool InitFbank(
}
}
py
::
array_t
<
double
>
ComputeFbankStreaming
(
const
py
::
array_t
<
double
>&
wav
)
{
py
::
array_t
<
double
>
ComputeFbankStreaming
(
const
py
::
array_t
<
double
>&
wav
)
{
return
paddleaudio
::
KaldiFeatureWrapper
::
GetInstance
()
->
ComputeFbank
(
wav
);
return
paddleaudio
::
KaldiFeatureWrapper
::
GetInstance
()
->
ComputeFbank
(
wav
);
}
}
py
::
array_t
<
double
>
ComputeFbank
(
py
::
array_t
<
double
>
ComputeFbank
(
float
samp_freq
,
// frame opts
float
samp_freq
,
// frame opts
float
frame_shift_ms
,
float
frame_shift_ms
,
float
frame_length_ms
,
float
frame_length_ms
,
float
dither
,
float
dither
,
float
preemph_coeff
,
float
preemph_coeff
,
bool
remove_dc_offset
,
bool
remove_dc_offset
,
std
::
string
window_type
,
// e.g. Hamming window
std
::
string
window_type
,
// e.g. Hamming window
bool
round_to_power_of_two
,
bool
round_to_power_of_two
,
float
blackman_coeff
,
float
blackman_coeff
,
bool
snip_edges
,
bool
snip_edges
,
bool
allow_downsample
,
bool
allow_downsample
,
bool
allow_upsample
,
bool
allow_upsample
,
int
max_feature_vectors
,
int
max_feature_vectors
,
int
num_bins
,
// mel opts
int
num_bins
,
// mel opts
float
low_freq
,
float
low_freq
,
float
high_freq
,
float
high_freq
,
float
vtln_low
,
float
vtln_low
,
float
vtln_high
,
float
vtln_high
,
bool
debug_mel
,
bool
debug_mel
,
bool
htk_mode
,
bool
htk_mode
,
bool
use_energy
,
// fbank opts
bool
use_energy
,
// fbank opts
float
energy_floor
,
float
energy_floor
,
bool
raw_energy
,
bool
raw_energy
,
bool
htk_compat
,
bool
htk_compat
,
bool
use_log_fbank
,
bool
use_log_fbank
,
bool
use_power
,
bool
use_power
,
const
py
::
array_t
<
double
>&
wav
)
{
const
py
::
array_t
<
double
>&
wav
)
{
InitFbank
(
samp_freq
,
// frame opts
InitFbank
(
samp_freq
,
// frame opts
frame_shift_ms
,
frame_shift_ms
,
frame_length_ms
,
frame_length_ms
,
dither
,
dither
,
preemph_coeff
,
preemph_coeff
,
remove_dc_offset
,
remove_dc_offset
,
window_type
,
// e.g. Hamming window
window_type
,
// e.g. Hamming window
round_to_power_of_two
,
round_to_power_of_two
,
blackman_coeff
,
blackman_coeff
,
snip_edges
,
snip_edges
,
allow_downsample
,
allow_downsample
,
allow_upsample
,
allow_upsample
,
max_feature_vectors
,
max_feature_vectors
,
num_bins
,
// mel opts
num_bins
,
// mel opts
low_freq
,
low_freq
,
high_freq
,
high_freq
,
vtln_low
,
vtln_low
,
vtln_high
,
vtln_high
,
debug_mel
,
debug_mel
,
htk_mode
,
htk_mode
,
use_energy
,
// fbank opts
use_energy
,
// fbank opts
energy_floor
,
energy_floor
,
raw_energy
,
raw_energy
,
htk_compat
,
htk_compat
,
use_log_fbank
,
use_log_fbank
,
use_power
);
use_power
);
py
::
array_t
<
double
>
result
=
ComputeFbankStreaming
(
wav
);
py
::
array_t
<
double
>
result
=
ComputeFbankStreaming
(
wav
);
paddleaudio
::
KaldiFeatureWrapper
::
GetInstance
()
->
ResetFbank
();
paddleaudio
::
KaldiFeatureWrapper
::
GetInstance
()
->
ResetFbank
();
return
result
;
return
result
;
}
}
void
ResetFbank
()
{
void
ResetFbank
()
{
paddleaudio
::
KaldiFeatureWrapper
::
GetInstance
()
->
ResetFbank
();
paddleaudio
::
KaldiFeatureWrapper
::
GetInstance
()
->
ResetFbank
();
}
}
PYBIND11_MODULE
(
kaldi_featurepy
,
m
)
{
PYBIND11_MODULE
(
kaldi_featurepy
,
m
)
{
...
@@ -139,5 +138,7 @@ PYBIND11_MODULE(kaldi_featurepy, m) {
...
@@ -139,5 +138,7 @@ PYBIND11_MODULE(kaldi_featurepy, m) {
m
.
def
(
"InitFbank"
,
&
InitFbank
,
"init fbank"
);
m
.
def
(
"InitFbank"
,
&
InitFbank
,
"init fbank"
);
m
.
def
(
"ResetFbank"
,
&
ResetFbank
,
"reset fbank"
);
m
.
def
(
"ResetFbank"
,
&
ResetFbank
,
"reset fbank"
);
m
.
def
(
"ComputeFbank"
,
&
ComputeFbank
,
"compute 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
浏览文件 @
a3911ab5
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include "kaldi_feature_wrapper.h"
#include "kaldi_feature_wrapper.h"
namespace
py
=
pybind11
;
namespace
py
=
pybind11
;
bool
InitFbank
(
bool
InitFbank
(
float
samp_freq
,
// frame opts
float
samp_freq
,
// frame opts
float
frame_shift_ms
,
float
frame_shift_ms
,
float
frame_length_ms
,
float
frame_length_ms
,
float
dither
,
float
dither
,
float
preemph_coeff
,
float
preemph_coeff
,
bool
remove_dc_offset
,
bool
remove_dc_offset
,
std
::
string
window_type
,
// e.g. Hamming window
std
::
string
window_type
,
// e.g. Hamming window
bool
round_to_power_of_two
,
bool
round_to_power_of_two
,
float
blackman_coeff
,
float
blackman_coeff
,
bool
snip_edges
,
bool
snip_edges
,
bool
allow_downsample
,
bool
allow_downsample
,
bool
allow_upsample
,
bool
allow_upsample
,
int
max_feature_vectors
,
int
max_feature_vectors
,
int
num_bins
,
// mel opts
int
num_bins
,
// mel opts
float
low_freq
,
float
low_freq
,
float
high_freq
,
float
high_freq
,
float
vtln_low
,
float
vtln_low
,
float
vtln_high
,
float
vtln_high
,
bool
debug_mel
,
bool
debug_mel
,
bool
htk_mode
,
bool
htk_mode
,
bool
use_energy
,
// fbank opts
bool
use_energy
,
// fbank opts
float
energy_floor
,
float
energy_floor
,
bool
raw_energy
,
bool
raw_energy
,
bool
htk_compat
,
bool
htk_compat
,
bool
use_log_fbank
,
bool
use_log_fbank
,
bool
use_power
);
bool
use_power
);
py
::
array_t
<
double
>
ComputeFbank
(
py
::
array_t
<
double
>
ComputeFbank
(
float
samp_freq
,
// frame opts
float
samp_freq
,
// frame opts
float
frame_shift_ms
,
float
frame_shift_ms
,
float
frame_length_ms
,
float
frame_length_ms
,
float
dither
,
float
dither
,
float
preemph_coeff
,
float
preemph_coeff
,
bool
remove_dc_offset
,
bool
remove_dc_offset
,
std
::
string
window_type
,
// e.g. Hamming window
std
::
string
window_type
,
// e.g. Hamming window
bool
round_to_power_of_two
,
bool
round_to_power_of_two
,
kaldi
::
BaseFloat
blackman_coeff
,
kaldi
::
BaseFloat
blackman_coeff
,
bool
snip_edges
,
bool
snip_edges
,
bool
allow_downsample
,
bool
allow_downsample
,
bool
allow_upsample
,
bool
allow_upsample
,
int
max_feature_vectors
,
int
max_feature_vectors
,
int
num_bins
,
// mel opts
int
num_bins
,
// mel opts
float
low_freq
,
float
low_freq
,
float
high_freq
,
float
high_freq
,
float
vtln_low
,
float
vtln_low
,
float
vtln_high
,
float
vtln_high
,
bool
debug_mel
,
bool
debug_mel
,
bool
htk_mode
,
bool
htk_mode
,
bool
use_energy
,
// fbank opts
bool
use_energy
,
// fbank opts
float
energy_floor
,
float
energy_floor
,
bool
raw_energy
,
bool
raw_energy
,
bool
htk_compat
,
bool
htk_compat
,
...
...
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.cc
浏览文件 @
a3911ab5
...
@@ -8,17 +8,18 @@ KaldiFeatureWrapper* KaldiFeatureWrapper::GetInstance() {
...
@@ -8,17 +8,18 @@ KaldiFeatureWrapper* KaldiFeatureWrapper::GetInstance() {
}
}
bool
KaldiFeatureWrapper
::
InitFbank
(
kaldi
::
FbankOptions
opts
)
{
bool
KaldiFeatureWrapper
::
InitFbank
(
kaldi
::
FbankOptions
opts
)
{
fbank_
.
reset
(
new
Fbank
(
opts
));
fbank_
.
reset
(
new
Fbank
(
opts
));
return
true
;
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
();
py
::
buffer_info
info
=
wav
.
request
();
kaldi
::
Vector
<
kaldi
::
BaseFloat
>
input_wav
(
info
.
size
);
kaldi
::
Vector
<
kaldi
::
BaseFloat
>
input_wav
(
info
.
size
);
double
*
wav_ptr
=
(
double
*
)
info
.
ptr
;
double
*
wav_ptr
=
(
double
*
)
info
.
ptr
;
for
(
int
idx
=
0
;
idx
<
info
.
size
;
++
idx
)
{
for
(
int
idx
=
0
;
idx
<
info
.
size
;
++
idx
)
{
input_wav
(
idx
)
=
*
wav_ptr
;
input_wav
(
idx
)
=
*
wav_ptr
;
wav_ptr
++
;
wav_ptr
++
;
}
}
...
@@ -28,8 +29,8 @@ py::array_t<double> KaldiFeatureWrapper::ComputeFbank(const py::array_t<double>
...
@@ -28,8 +29,8 @@ py::array_t<double> KaldiFeatureWrapper::ComputeFbank(const py::array_t<double>
auto
result
=
py
::
array_t
<
double
>
(
feats
.
Dim
());
auto
result
=
py
::
array_t
<
double
>
(
feats
.
Dim
());
py
::
buffer_info
xs
=
result
.
request
();
py
::
buffer_info
xs
=
result
.
request
();
for
(
int
idx
=
0
;
idx
<
10
;
++
idx
)
{
for
(
int
idx
=
0
;
idx
<
10
;
++
idx
)
{
float
val
=
feats
(
idx
);
float
val
=
feats
(
idx
);
std
::
cout
<<
val
<<
" "
;
std
::
cout
<<
val
<<
" "
;
}
}
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
double
*
res_ptr
=
(
double
*
)
xs
.
ptr
;
double
*
res_ptr
=
(
double
*
)
xs
.
ptr
;
...
@@ -38,20 +39,21 @@ py::array_t<double> KaldiFeatureWrapper::ComputeFbank(const py::array_t<double>
...
@@ -38,20 +39,21 @@ py::array_t<double> KaldiFeatureWrapper::ComputeFbank(const py::array_t<double>
res_ptr
++
;
res_ptr
++
;
}
}
return
result
.
reshape
({
feats
.
Dim
()
/
Dim
(),
Dim
()});
return
result
.
reshape
({
feats
.
Dim
()
/
Dim
(),
Dim
()});
/*
/*
py::buffer_info info = wav.request();
py::buffer_info info = wav.request();
std::cout << info.size << std::endl;
std::cout << info.size << std::endl;
auto result = py::array_t<double>(info.size);
auto result = py::array_t<double>(info.size);
//kaldi::Vector<kaldi::BaseFloat> input_wav(info.size);
//kaldi::Vector<kaldi::BaseFloat> input_wav(info.size);
kaldi::Vector<double> input_wav(info.size);
kaldi::Vector<double> input_wav(info.size);
py::buffer_info info_re = result.request();
py::buffer_info info_re = result.request();
memcpy(input_wav.Data(), (double*)info.ptr, wav.nbytes());
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()*
return result;
sizeof(double));
*/
return result;
*/
}
}
}
// namespace paddleaudio
}
// namespace paddleaudio
paddlespeech/audio/src/pybind/kaldi_frontend/kaldi_feature_wrapper.h
浏览文件 @
a3911ab5
#include "base/kaldi-common.h"
#include "base/kaldi-common.h"
#include "feature_common.h"
#include "feat/feature-fbank.h"
#include "feat/feature-fbank.h"
#include "feature_common.h"
#pragma once
#pragma once
...
@@ -14,12 +14,8 @@ class KaldiFeatureWrapper {
...
@@ -14,12 +14,8 @@ class KaldiFeatureWrapper {
static
KaldiFeatureWrapper
*
GetInstance
();
static
KaldiFeatureWrapper
*
GetInstance
();
bool
InitFbank
(
kaldi
::
FbankOptions
opts
);
bool
InitFbank
(
kaldi
::
FbankOptions
opts
);
py
::
array_t
<
double
>
ComputeFbank
(
const
py
::
array_t
<
double
>
wav
);
py
::
array_t
<
double
>
ComputeFbank
(
const
py
::
array_t
<
double
>
wav
);
int
Dim
()
{
int
Dim
()
{
return
fbank_
->
Dim
();
}
return
fbank_
->
Dim
();
void
ResetFbank
()
{
fbank_
->
Reset
();
}
}
void
ResetFbank
()
{
fbank_
->
Reset
();
}
private:
private:
std
::
unique_ptr
<
paddleaudio
::
Fbank
>
fbank_
;
std
::
unique_ptr
<
paddleaudio
::
Fbank
>
fbank_
;
...
...
paddlespeech/audio/src/pybind/pybind.cpp
浏览文件 @
a3911ab5
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
All rights reserved.
#include "paddlespeech/audio/src/pybind/sox/io.h"
#include "paddlespeech/audio/src/pybind/sox/io.h"
PYBIND11_MODULE
(
_paddleaudio
,
m
)
{
PYBIND11_MODULE
(
_paddleaudio
,
m
)
{
m
.
def
(
"get_info_file"
,
&
paddleaudio
::
sox_io
::
get_info_file
,
m
.
def
(
"get_info_file"
,
"Get metadata of audio file."
);
&
paddleaudio
::
sox_io
::
get_info_file
,
m
.
def
(
"get_info_fileobj"
,
&
paddleaudio
::
sox_io
::
get_info_fileobj
,
"Get metadata of audio file."
);
"Get metadata of audio in file object."
);
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
浏览文件 @
a3911ab5
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
All rights reserved.
#include "paddlespeech/audio/src/pybind/sox/io.h"
#include "paddlespeech/audio/src/pybind/sox/io.h"
#include "paddlespeech/audio/src/pybind/sox/utils.h"
#include "paddlespeech/audio/src/pybind/sox/utils.h"
...
@@ -11,51 +11,54 @@ namespace sox_io {
...
@@ -11,51 +11,54 @@ namespace sox_io {
auto
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
format
)
auto
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
SoxFormat
sf
(
sox_open_read
(
path
.
data
(),
SoxFormat
sf
(
/*signal=*/
nullptr
,
sox_open_read
(
path
.
data
(),
/*encoding=*/
nullptr
,
/*signal=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
/*encoding=*/
nullptr
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
validate_input_file
(
sf
,
path
);
validate_input_file
(
sf
,
path
);
return
std
::
make_tuple
(
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
return
std
::
make_tuple
(
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
get_encoding
(
sf
->
encoding
.
encoding
));
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
get_encoding
(
sf
->
encoding
.
encoding
));
}
}
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
{
const
auto
capacity
=
[
&
]()
{
const
auto
capacity
=
[
&
]()
{
const
auto
bufsiz
=
get_buffer_size
();
const
auto
bufsiz
=
get_buffer_size
();
const
int64_t
kDefaultCapacityInBytes
=
4096
;
const
int64_t
kDefaultCapacityInBytes
=
4096
;
return
(
bufsiz
>
kDefaultCapacityInBytes
)
?
bufsiz
return
(
bufsiz
>
kDefaultCapacityInBytes
)
?
bufsiz
:
kDefaultCapacityInBytes
;
:
kDefaultCapacityInBytes
;
}();
}();
std
::
string
buffer
(
capacity
,
'\0'
);
std
::
string
buffer
(
capacity
,
'\0'
);
auto
*
buf
=
const_cast
<
char
*>
(
buffer
.
data
());
auto
*
buf
=
const_cast
<
char
*>
(
buffer
.
data
());
auto
num_read
=
read_fileobj
(
&
fileobj
,
capacity
,
buf
);
auto
num_read
=
read_fileobj
(
&
fileobj
,
capacity
,
buf
);
// If the file is shorter than 256, then libsox cannot read the header.
// If the file is shorter than 256, then libsox cannot read the header.
auto
buf_size
=
(
num_read
>
256
)
?
num_read
:
256
;
auto
buf_size
=
(
num_read
>
256
)
?
num_read
:
256
;
SoxFormat
sf
(
sox_open_mem_read
(
buf
,
buf_size
,
SoxFormat
sf
(
sox_open_mem_read
(
/*signal=*/
nullptr
,
buf
,
/*encoding=*/
nullptr
,
buf_size
,
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
/*signal=*/
nullptr
,
/*encoding=*/
nullptr
,
// In case of streamed data, length can be 0
/*filetype=*/
format
.
empty
()
?
nullptr
:
format
.
data
()));
validate_input_memfile
(
sf
);
// In case of streamed data, length can be 0
return
std
::
make_tuple
(
validate_input_memfile
(
sf
);
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
return
std
::
make_tuple
(
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
get_encoding
(
sf
->
encoding
.
encoding
));
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
get_encoding
(
sf
->
encoding
.
encoding
));
}
}
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_io
}
// namespace sox_io
paddlespeech/audio/src/pybind/sox/io.h
浏览文件 @
a3911ab5
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
All rights reserved.
#ifndef PADDLEAUDIO_PYBIND_SOX_IO_H
#ifndef PADDLEAUDIO_PYBIND_SOX_IO_H
#define PADDLEAUDIO_PYBIND_SOX_IO_H
#define PADDLEAUDIO_PYBIND_SOX_IO_H
...
@@ -15,7 +15,7 @@ auto get_info_file(const std::string &path, const std::string &format)
...
@@ -15,7 +15,7 @@ auto get_info_file(const std::string &path, const std::string &format)
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
auto
get_info_fileobj
(
py
::
object
fileobj
,
const
std
::
string
&
format
)
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
->
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_io
}
// namespace sox_io
#endif
#endif
paddlespeech/audio/src/pybind/sox/utils.cpp
浏览文件 @
a3911ab5
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
All rights reserved.
#include "paddlespeech/audio/src/pybind/sox/utils.h"
#include "paddlespeech/audio/src/pybind/sox/utils.h"
...
@@ -15,86 +15,87 @@ sox_format_t *SoxFormat::operator->() const noexcept { return fd_; }
...
@@ -15,86 +15,87 @@ sox_format_t *SoxFormat::operator->() const noexcept { return fd_; }
SoxFormat
::
operator
sox_format_t
*
()
const
noexcept
{
return
fd_
;
}
SoxFormat
::
operator
sox_format_t
*
()
const
noexcept
{
return
fd_
;
}
void
SoxFormat
::
close
()
{
void
SoxFormat
::
close
()
{
if
(
fd_
!=
nullptr
)
{
if
(
fd_
!=
nullptr
)
{
sox_close
(
fd_
);
sox_close
(
fd_
);
fd_
=
nullptr
;
fd_
=
nullptr
;
}
}
}
}
auto
read_fileobj
(
py
::
object
*
fileobj
,
const
uint64_t
size
,
char
*
buffer
)
auto
read_fileobj
(
py
::
object
*
fileobj
,
const
uint64_t
size
,
char
*
buffer
)
->
uint64_t
{
->
uint64_t
{
uint64_t
num_read
=
0
;
uint64_t
num_read
=
0
;
while
(
num_read
<
size
)
{
while
(
num_read
<
size
)
{
auto
request
=
size
-
num_read
;
auto
request
=
size
-
num_read
;
auto
chunk
=
static_cast
<
std
::
string
>
(
auto
chunk
=
static_cast
<
std
::
string
>
(
static_cast
<
py
::
bytes
>
(
fileobj
->
attr
(
"read"
)(
request
)));
static_cast
<
py
::
bytes
>
(
fileobj
->
attr
(
"read"
)(
request
)));
auto
chunk_len
=
chunk
.
length
();
auto
chunk_len
=
chunk
.
length
();
if
(
chunk_len
==
0
)
{
if
(
chunk_len
==
0
)
{
break
;
break
;
}
}
if
(
chunk_len
>
request
)
{
if
(
chunk_len
>
request
)
{
std
::
ostringstream
message
;
std
::
ostringstream
message
;
message
<<
"Requested up to "
<<
request
<<
" bytes but, "
message
<<
"received "
<<
chunk_len
<<
" bytes. "
<<
"Requested up to "
<<
request
<<
" bytes but, "
<<
"The given object does not confirm to read protocol of file "
<<
"received "
<<
chunk_len
<<
" bytes. "
"object."
;
<<
"The given object does not confirm to read protocol of file "
throw
std
::
runtime_error
(
message
.
str
());
"object."
;
throw
std
::
runtime_error
(
message
.
str
());
}
memcpy
(
buffer
,
chunk
.
data
(),
chunk_len
);
buffer
+=
chunk_len
;
num_read
+=
chunk_len
;
}
}
memcpy
(
buffer
,
chunk
.
data
(),
chunk_len
);
return
num_read
;
buffer
+=
chunk_len
;
num_read
+=
chunk_len
;
}
return
num_read
;
}
}
int64_t
get_buffer_size
()
{
return
sox_get_globals
()
->
bufsiz
;
}
int64_t
get_buffer_size
()
{
return
sox_get_globals
()
->
bufsiz
;
}
void
validate_input_file
(
const
SoxFormat
&
sf
,
const
std
::
string
&
path
)
{
void
validate_input_file
(
const
SoxFormat
&
sf
,
const
std
::
string
&
path
)
{
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
throw
std
::
runtime_error
(
"Error loading audio file: failed to open file "
+
throw
std
::
runtime_error
(
path
);
"Error loading audio file: failed to open file "
+
path
);
}
}
if
(
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
if
(
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
throw
std
::
runtime_error
(
"Error loading audio file: unknown encoding."
);
throw
std
::
runtime_error
(
"Error loading audio file: unknown encoding."
);
}
}
}
}
void
validate_input_memfile
(
const
SoxFormat
&
sf
)
{
void
validate_input_memfile
(
const
SoxFormat
&
sf
)
{
return
validate_input_file
(
sf
,
"<in memory buffer>"
);
return
validate_input_file
(
sf
,
"<in memory buffer>"
);
}
}
std
::
string
get_encoding
(
sox_encoding_t
encoding
)
{
std
::
string
get_encoding
(
sox_encoding_t
encoding
)
{
switch
(
encoding
)
{
switch
(
encoding
)
{
case
SOX_ENCODING_UNKNOWN
:
case
SOX_ENCODING_UNKNOWN
:
return
"UNKNOWN"
;
return
"UNKNOWN"
;
case
SOX_ENCODING_SIGN2
:
case
SOX_ENCODING_SIGN2
:
return
"PCM_S"
;
return
"PCM_S"
;
case
SOX_ENCODING_UNSIGNED
:
case
SOX_ENCODING_UNSIGNED
:
return
"PCM_U"
;
return
"PCM_U"
;
case
SOX_ENCODING_FLOAT
:
case
SOX_ENCODING_FLOAT
:
return
"PCM_F"
;
return
"PCM_F"
;
case
SOX_ENCODING_FLAC
:
case
SOX_ENCODING_FLAC
:
return
"FLAC"
;
return
"FLAC"
;
case
SOX_ENCODING_ULAW
:
case
SOX_ENCODING_ULAW
:
return
"ULAW"
;
return
"ULAW"
;
case
SOX_ENCODING_ALAW
:
case
SOX_ENCODING_ALAW
:
return
"ALAW"
;
return
"ALAW"
;
case
SOX_ENCODING_MP3
:
case
SOX_ENCODING_MP3
:
return
"MP3"
;
return
"MP3"
;
case
SOX_ENCODING_VORBIS
:
case
SOX_ENCODING_VORBIS
:
return
"VORBIS"
;
return
"VORBIS"
;
case
SOX_ENCODING_AMR_WB
:
case
SOX_ENCODING_AMR_WB
:
return
"AMR_WB"
;
return
"AMR_WB"
;
case
SOX_ENCODING_AMR_NB
:
case
SOX_ENCODING_AMR_NB
:
return
"AMR_NB"
;
return
"AMR_NB"
;
case
SOX_ENCODING_OPUS
:
case
SOX_ENCODING_OPUS
:
return
"OPUS"
;
return
"OPUS"
;
case
SOX_ENCODING_GSM
:
case
SOX_ENCODING_GSM
:
return
"GSM"
;
return
"GSM"
;
default:
default:
return
"UNKNOWN"
;
return
"UNKNOWN"
;
}
}
}
}
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_utils
}
// namespace sox_utils
paddlespeech/audio/src/pybind/sox/utils.h
浏览文件 @
a3911ab5
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
All rights reserved.
#ifndef PADDLEAUDIO_PYBIND_SOX_UTILS_H
#ifndef PADDLEAUDIO_PYBIND_SOX_UTILS_H
#define PADDLEAUDIO_PYBIND_SOX_UTILS_H
#define PADDLEAUDIO_PYBIND_SOX_UTILS_H
...
@@ -14,19 +14,19 @@ namespace sox_utils {
...
@@ -14,19 +14,19 @@ namespace sox_utils {
/// helper class to automatically close sox_format_t*
/// helper class to automatically close sox_format_t*
struct
SoxFormat
{
struct
SoxFormat
{
explicit
SoxFormat
(
sox_format_t
*
fd
)
noexcept
;
explicit
SoxFormat
(
sox_format_t
*
fd
)
noexcept
;
SoxFormat
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
(
SoxFormat
&&
other
)
=
delete
;
SoxFormat
(
SoxFormat
&&
other
)
=
delete
;
SoxFormat
&
operator
=
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
&
operator
=
(
const
SoxFormat
&
other
)
=
delete
;
SoxFormat
&
operator
=
(
SoxFormat
&&
other
)
=
delete
;
SoxFormat
&
operator
=
(
SoxFormat
&&
other
)
=
delete
;
~
SoxFormat
();
~
SoxFormat
();
sox_format_t
*
operator
->
()
const
noexcept
;
sox_format_t
*
operator
->
()
const
noexcept
;
operator
sox_format_t
*
()
const
noexcept
;
operator
sox_format_t
*
()
const
noexcept
;
void
close
();
void
close
();
private:
private:
sox_format_t
*
fd_
;
sox_format_t
*
fd_
;
};
};
auto
read_fileobj
(
py
::
object
*
fileobj
,
uint64_t
size
,
char
*
buffer
)
->
uint64_t
;
auto
read_fileobj
(
py
::
object
*
fileobj
,
uint64_t
size
,
char
*
buffer
)
->
uint64_t
;
...
@@ -39,7 +39,7 @@ void validate_input_memfile(const SoxFormat &sf);
...
@@ -39,7 +39,7 @@ void validate_input_memfile(const SoxFormat &sf);
std
::
string
get_encoding
(
sox_encoding_t
encoding
);
std
::
string
get_encoding
(
sox_encoding_t
encoding
);
}
// namespace paddleaudio
}
// namespace paddleaudio
}
// namespace sox_utils
}
// namespace sox_utils
#endif
#endif
paddlespeech/audio/src/sox/io.cpp
浏览文件 @
a3911ab5
...
@@ -11,54 +11,53 @@ namespace paddleaudio {
...
@@ -11,54 +11,53 @@ namespace paddleaudio {
namespace
sox_io
{
namespace
sox_io
{
tl
::
optional
<
MetaDataTuple
>
get_info_file
(
tl
::
optional
<
MetaDataTuple
>
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
path
,
const
tl
::
optional
<
std
::
string
>&
format
)
{
const
tl
::
optional
<
std
::
string
>&
format
)
{
SoxFormat
sf
(
sox_open_read
(
SoxFormat
sf
(
sox_open_read
(
path
.
c_str
(),
path
.
c_str
(),
/*signal=*/
nullptr
,
/*signal=*/
nullptr
,
/*encoding=*/
nullptr
,
/*encoding=*/
nullptr
,
/*filetype=*/
format
.
has_value
()
?
format
.
value
().
c_str
()
:
nullptr
));
/*filetype=*/
format
.
has_value
()
?
format
.
value
().
c_str
()
:
nullptr
));
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
||
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
||
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
sf
->
encoding
.
encoding
==
SOX_ENCODING_UNKNOWN
)
{
return
{};
return
{};
}
}
return
std
::
forward_as_tuple
(
return
std
::
forward_as_tuple
(
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
signal
.
rate
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
length
/
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
signal
.
channels
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
static_cast
<
int64_t
>
(
sf
->
encoding
.
bits_per_sample
),
get_encoding
(
sf
->
encoding
.
encoding
));
get_encoding
(
sf
->
encoding
.
encoding
));
}
}
std
::
vector
<
std
::
vector
<
std
::
string
>>
get_effects
(
std
::
vector
<
std
::
vector
<
std
::
string
>>
get_effects
(
const
tl
::
optional
<
int64_t
>&
frame_offset
,
const
tl
::
optional
<
int64_t
>&
frame_offset
,
const
tl
::
optional
<
int64_t
>&
num_frames
)
{
const
tl
::
optional
<
int64_t
>&
num_frames
)
{
const
auto
offset
=
frame_offset
.
value_or
(
0
);
const
auto
offset
=
frame_offset
.
value_or
(
0
);
if
(
offset
<
0
)
{
if
(
offset
<
0
)
{
throw
std
::
runtime_error
(
throw
std
::
runtime_error
(
"Invalid argument: frame_offset must be non-negative."
);
"Invalid argument: frame_offset must be non-negative."
);
}
}
const
auto
frames
=
num_frames
.
value_or
(
-
1
);
const
auto
frames
=
num_frames
.
value_or
(
-
1
);
if
(
frames
==
0
||
frames
<
-
1
)
{
if
(
frames
==
0
||
frames
<
-
1
)
{
throw
std
::
runtime_error
(
throw
std
::
runtime_error
(
"Invalid argument: num_frames must be -1 or greater than 0."
);
"Invalid argument: num_frames must be -1 or greater than 0."
);
}
}
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
;
std
::
vector
<
std
::
vector
<
std
::
string
>>
effects
;
if
(
frames
!=
-
1
)
{
if
(
frames
!=
-
1
)
{
std
::
ostringstream
os_offset
,
os_frames
;
std
::
ostringstream
os_offset
,
os_frames
;
os_offset
<<
offset
<<
"s"
;
os_offset
<<
offset
<<
"s"
;
os_frames
<<
"+"
<<
frames
<<
"s"
;
os_frames
<<
"+"
<<
frames
<<
"s"
;
effects
.
emplace_back
(
effects
.
emplace_back
(
std
::
vector
<
std
::
string
>
{
"trim"
,
os_offset
.
str
(),
os_frames
.
str
()});
std
::
vector
<
std
::
string
>
{
"trim"
,
os_offset
.
str
(),
os_frames
.
str
()});
}
else
if
(
offset
!=
0
)
{
}
else
if
(
offset
!=
0
)
{
std
::
ostringstream
os_offset
;
std
::
ostringstream
os_offset
;
os_offset
<<
offset
<<
"s"
;
os_offset
<<
offset
<<
"s"
;
effects
.
emplace_back
(
std
::
vector
<
std
::
string
>
{
"trim"
,
os_offset
.
str
()});
effects
.
emplace_back
(
std
::
vector
<
std
::
string
>
{
"trim"
,
os_offset
.
str
()});
}
}
return
effects
;
return
effects
;
}
}
tl
::
optional
<
std
::
tuple
<
torch
::
Tensor
,
int64_t
>>
load_audio_file
(
tl
::
optional
<
std
::
tuple
<
torch
::
Tensor
,
int64_t
>>
load_audio_file
(
...
@@ -68,79 +67,73 @@ tl::optional<std::tuple<torch::Tensor, int64_t>> load_audio_file(
...
@@ -68,79 +67,73 @@ tl::optional<std::tuple<torch::Tensor, int64_t>> load_audio_file(
tl
::
optional
<
bool
>
normalize
,
tl
::
optional
<
bool
>
normalize
,
tl
::
optional
<
bool
>
channels_first
,
tl
::
optional
<
bool
>
channels_first
,
const
tl
::
optional
<
std
::
string
>&
format
)
{
const
tl
::
optional
<
std
::
string
>&
format
)
{
auto
effects
=
get_effects
(
frame_offset
,
num_frames
);
auto
effects
=
get_effects
(
frame_offset
,
num_frames
);
return
paddleaudio
::
sox_effects
::
apply_effects_file
(
return
paddleaudio
::
sox_effects
::
apply_effects_file
(
path
,
effects
,
normalize
,
channels_first
,
format
);
path
,
effects
,
normalize
,
channels_first
,
format
);
}
}
void
save_audio_file
(
void
save_audio_file
(
const
std
::
string
&
path
,
const
std
::
string
&
path
,
torch
::
Tensor
tensor
,
torch
::
Tensor
tensor
,
int64_t
sample_rate
,
int64_t
sample_rate
,
bool
channels_first
,
bool
channels_first
,
tl
::
optional
<
double
>
compression
,
tl
::
optional
<
double
>
compression
,
tl
::
optional
<
std
::
string
>
format
,
tl
::
optional
<
std
::
string
>
format
,
tl
::
optional
<
std
::
string
>
encoding
,
tl
::
optional
<
std
::
string
>
encoding
,
tl
::
optional
<
int64_t
>
bits_per_sample
)
{
tl
::
optional
<
int64_t
>
bits_per_sample
)
{
validate_input_tensor
(
tensor
);
validate_input_tensor
(
tensor
);
const
auto
filetype
=
[
&
]()
{
const
auto
filetype
=
[
&
]()
{
if
(
format
.
has_value
())
return
format
.
value
();
if
(
format
.
has_value
())
return
get_filetype
(
path
);
return
format
.
value
();
}();
return
get_filetype
(
path
);
}();
if
(
filetype
==
"amr-nb"
)
{
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
if
(
filetype
==
"amr-nb"
)
{
TORCH_CHECK
(
num_channels
==
1
,
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
"amr-nb format only supports single channel audio."
);
TORCH_CHECK
(
}
else
if
(
filetype
==
"htk"
)
{
num_channels
==
1
,
"amr-nb format only supports single channel audio."
);
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
}
else
if
(
filetype
==
"htk"
)
{
TORCH_CHECK
(
num_channels
==
1
,
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
"htk format only supports single channel audio."
);
TORCH_CHECK
(
}
else
if
(
filetype
==
"gsm"
)
{
num_channels
==
1
,
"htk format only supports single channel audio."
);
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
}
else
if
(
filetype
==
"gsm"
)
{
TORCH_CHECK
(
num_channels
==
1
,
const
auto
num_channels
=
tensor
.
size
(
channels_first
?
0
:
1
);
"gsm format only supports single channel audio."
);
TORCH_CHECK
(
TORCH_CHECK
(
sample_rate
==
8000
,
num_channels
==
1
,
"gsm format only supports single channel audio."
);
"gsm format only supports a sampling rate of 8kHz."
);
TORCH_CHECK
(
}
sample_rate
==
8000
,
const
auto
signal_info
=
"gsm format only supports a sampling rate of 8kHz."
);
get_signalinfo
(
&
tensor
,
sample_rate
,
filetype
,
channels_first
);
}
const
auto
encoding_info
=
get_encodinginfo_for_save
(
const
auto
signal_info
=
filetype
,
tensor
.
dtype
(),
compression
,
encoding
,
bits_per_sample
);
get_signalinfo
(
&
tensor
,
sample_rate
,
filetype
,
channels_first
);
const
auto
encoding_info
=
get_encodinginfo_for_save
(
SoxFormat
sf
(
sox_open_write
(
path
.
c_str
(),
filetype
,
tensor
.
dtype
(),
compression
,
encoding
,
bits_per_sample
);
&
signal_info
,
&
encoding_info
,
SoxFormat
sf
(
sox_open_write
(
/*filetype=*/
filetype
.
c_str
(),
path
.
c_str
(),
/*oob=*/
nullptr
,
&
signal_info
,
/*overwrite_permitted=*/
nullptr
));
&
encoding_info
,
/*filetype=*/
filetype
.
c_str
(),
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
/*oob=*/
nullptr
,
throw
std
::
runtime_error
(
/*overwrite_permitted=*/
nullptr
));
"Error saving audio file: failed to open file "
+
path
);
}
if
(
static_cast
<
sox_format_t
*>
(
sf
)
==
nullptr
)
{
throw
std
::
runtime_error
(
paddleaudio
::
sox_effects_chain
::
SoxEffectsChain
chain
(
"Error saving audio file: failed to open file "
+
path
);
/*input_encoding=*/
get_tensor_encodinginfo
(
tensor
.
dtype
()),
}
/*output_encoding=*/
sf
->
encoding
);
chain
.
addInputTensor
(
&
tensor
,
sample_rate
,
channels_first
);
paddleaudio
::
sox_effects_chain
::
SoxEffectsChain
chain
(
chain
.
addOutputFile
(
sf
);
/*input_encoding=*/
get_tensor_encodinginfo
(
tensor
.
dtype
()),
chain
.
run
();
/*output_encoding=*/
sf
->
encoding
);
chain
.
addInputTensor
(
&
tensor
,
sample_rate
,
channels_first
);
chain
.
addOutputFile
(
sf
);
chain
.
run
();
}
}
TORCH_LIBRARY_FRAGMENT
(
paddleaudio
,
m
)
{
TORCH_LIBRARY_FRAGMENT
(
paddleaudio
,
m
)
{
m
.
def
(
"paddleaudio::sox_io_get_info"
,
&
paddleaudio
::
sox_io
::
get_info_file
);
m
.
def
(
"paddleaudio::sox_io_get_info"
,
&
paddleaudio
::
sox_io
::
get_info_file
);
m
.
def
(
m
.
def
(
"paddleaudio::sox_io_load_audio_file"
,
"paddleaudio::sox_io_load_audio_file"
,
&
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"
,
&
paddleaudio
::
sox_io
::
save_audio_file
);
}
}
}
// namespace sox_io
}
// namespace sox_io
}
// namespace paddleaudio
}
// namespace paddleaudio
\ No newline at end of file
\ No newline at end of file
paddlespeech/audio/src/sox/io.h
浏览文件 @
a3911ab5
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//
Copyright (c) 2017 Facebook Inc. (Soumith Chintala),
//All rights reserved.
//
All rights reserved.
#ifndef PADDLEAUDIO_SOX_IO_H
#ifndef PADDLEAUDIO_SOX_IO_H
#define PADDLEAUDIO_SOX_IO_H
#define PADDLEAUDIO_SOX_IO_H
...
@@ -11,17 +11,15 @@
...
@@ -11,17 +11,15 @@
namespace
paddleaudio
{
namespace
paddleaudio
{
namespace
sox_io
{
namespace
sox_io
{
auto
get_effects
(
auto
get_effects
(
const
tl
::
optional
<
int64_t
>&
frame_offset
,
const
tl
::
optional
<
int64_t
>&
frame_offset
,
const
tl
::
optional
<
int64_t
>&
num_frames
)
const
tl
::
optional
<
int64_t
>&
num_frames
)
->
std
::
vector
<
std
::
vector
<
std
::
string
>>
;
->
std
::
vector
<
std
::
vector
<
std
::
string
>>
;
using
MetaDataTuple
=
using
MetaDataTuple
=
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
std
::
tuple
<
int64_t
,
int64_t
,
int64_t
,
int64_t
,
std
::
string
>
;
tl
::
optional
<
MetaDataTuple
>
get_info_file
(
tl
::
optional
<
MetaDataTuple
>
get_info_file
(
const
std
::
string
&
path
,
const
std
::
string
&
path
,
const
tl
::
optional
<
std
::
string
>&
format
);
const
tl
::
optional
<
std
::
string
>&
format
);
tl
::
optional
<
std
::
tuple
<
torch
::
Tensor
,
int64_t
>>
load_audio_file
(
tl
::
optional
<
std
::
tuple
<
torch
::
Tensor
,
int64_t
>>
load_audio_file
(
const
std
::
string
&
path
,
const
std
::
string
&
path
,
...
@@ -31,17 +29,16 @@ tl::optional<std::tuple<torch::Tensor, int64_t>> load_audio_file(
...
@@ -31,17 +29,16 @@ tl::optional<std::tuple<torch::Tensor, int64_t>> load_audio_file(
tl
::
optional
<
bool
>
channels_first
,
tl
::
optional
<
bool
>
channels_first
,
const
tl
::
optional
<
std
::
string
>&
format
);
const
tl
::
optional
<
std
::
string
>&
format
);
void
save_audio_file
(
void
save_audio_file
(
const
std
::
string
&
path
,
const
std
::
string
&
path
,
torch
::
Tensor
tensor
,
torch
::
Tensor
tensor
,
int64_t
sample_rate
,
int64_t
sample_rate
,
bool
channels_first
,
bool
channels_first
,
tl
::
optional
<
double
>
compression
,
tl
::
optional
<
double
>
compression
,
tl
::
optional
<
std
::
string
>
format
,
tl
::
optional
<
std
::
string
>
format
,
tl
::
optional
<
std
::
string
>
encoding
,
tl
::
optional
<
std
::
string
>
encoding
,
tl
::
optional
<
int64_t
>
bits_per_sample
);
tl
::
optional
<
int64_t
>
bits_per_sample
);
}
// namespace sox_io
}
// namespace sox_io
}
// namespace paddleaudio
}
// namespace paddleaudio
#endif
#endif
\ No newline at end of file
paddlespeech/audio/src/utils.cpp
浏览文件 @
a3911ab5
...
@@ -4,17 +4,17 @@ namespace {
...
@@ -4,17 +4,17 @@ namespace {
bool
is_sox_available
()
{
bool
is_sox_available
()
{
#ifdef INCLUDE_SOX
#ifdef INCLUDE_SOX
return
true
;
return
true
;
#else
#else
return
false
;
return
false
;
#endif
#endif
}
}
bool
is_kaldi_available
()
{
bool
is_kaldi_available
()
{
#ifdef INCLUDE_KALDI
#ifdef INCLUDE_KALDI
return
true
;
return
true
;
#else
#else
return
false
;
return
false
;
#endif
#endif
}
}
...
@@ -22,12 +22,12 @@ bool is_kaldi_available() {
...
@@ -22,12 +22,12 @@ bool is_kaldi_available() {
// not the runtime availability.
// not the runtime availability.
bool
is_ffmpeg_available
()
{
bool
is_ffmpeg_available
()
{
#ifdef USE_FFMPEG
#ifdef USE_FFMPEG
return
true
;
return
true
;
#else
#else
return
false
;
return
false
;
#endif
#endif
}
}
}
// namespace
}
// namespace
}
// namespace paddleaudio
}
// namespace paddleaudio
\ No newline at end of file
\ No newline at end of file
setup.py
浏览文件 @
a3911ab5
...
@@ -18,9 +18,9 @@ import os
...
@@ -18,9 +18,9 @@ import os
import
subprocess
as
sp
import
subprocess
as
sp
import
sys
import
sys
from
pathlib
import
Path
from
pathlib
import
Path
from
typing
import
Union
from
typing
import
Tuple
from
typing
import
List
from
typing
import
List
from
typing
import
Tuple
from
typing
import
Union
import
distutils.command.clean
import
distutils.command.clean
from
setuptools
import
Command
from
setuptools
import
Command
...
@@ -38,43 +38,13 @@ VERSION = '0.0.0'
...
@@ -38,43 +38,13 @@ VERSION = '0.0.0'
COMMITID
=
'none'
COMMITID
=
'none'
base
=
[
base
=
[
"editdistance"
,
"editdistance"
,
"g2p_en"
,
"g2pM"
,
"h5py"
,
"inflect"
,
"jieba"
,
"jsonlines"
,
"g2p_en"
,
"kaldiio"
,
"librosa==0.8.1"
,
"loguru"
,
"matplotlib"
,
"nara_wpe"
,
"g2pM"
,
"onnxruntime"
,
"pandas"
,
"paddlenlp"
,
"paddlespeech_feat"
,
"praatio==5.0.0"
,
"h5py"
,
"pypinyin"
,
"pypinyin-dict"
,
"python-dateutil"
,
"pyworld"
,
"resampy==0.2.2"
,
"inflect"
,
"sacrebleu"
,
"scipy"
,
"sentencepiece~=0.1.96"
,
"soundfile~=0.10"
,
"jieba"
,
"textgrid"
,
"timer"
,
"tqdm"
,
"typeguard"
,
"visualdl"
,
"webrtcvad"
,
"jsonlines"
,
"yacs~=0.1.8"
,
"prettytable"
,
"zhon"
,
'colorlog'
,
'pathos == 0.2.8'
"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
=
[
server
=
[
...
@@ -264,8 +234,9 @@ class clean(distutils.command.clean.clean):
...
@@ -264,8 +234,9 @@ class clean(distutils.command.clean.clean):
print
(
f
"removing '
{
path
}
' (and everything under it)"
)
print
(
f
"removing '
{
path
}
' (and everything under it)"
)
shutil
.
rmtree
(
str
(
path
),
ignore_errors
=
True
)
shutil
.
rmtree
(
str
(
path
),
ignore_errors
=
True
)
def
main
():
def
main
():
sha
=
check_output
([
"git"
,
"rev-parse"
,
"HEAD"
])
# commit id
sha
=
check_output
([
"git"
,
"rev-parse"
,
"HEAD"
])
# commit id
branch
=
check_output
([
"git"
,
"rev-parse"
,
"--abbrev-ref"
,
"HEAD"
])
branch
=
check_output
([
"git"
,
"rev-parse"
,
"--abbrev-ref"
,
"HEAD"
])
tag
=
check_output
([
"git"
,
"describe"
,
"--tags"
,
"--exact-match"
,
"@"
])
tag
=
check_output
([
"git"
,
"describe"
,
"--tags"
,
"--exact-match"
,
"@"
])
print
(
"-- Git branch:"
,
branch
)
print
(
"-- Git branch:"
,
branch
)
...
@@ -319,7 +290,8 @@ def main():
...
@@ -319,7 +290,8 @@ def main():
requirements
[
"develop"
],
requirements
[
"develop"
],
'doc'
:
[
'doc'
:
[
"sphinx"
,
"sphinx-rtd-theme"
,
"numpydoc"
,
"myst_parser"
,
"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'
],
'test'
:
[
'nose'
,
'torchaudio==0.10.2'
],
},
},
...
@@ -358,5 +330,6 @@ def main():
...
@@ -358,5 +330,6 @@ def main():
setup
(
**
setup_info
)
setup
(
**
setup_info
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
main
()
main
()
\ No newline at end of file
speechx/examples/ds2_ol/onnx/local/onnx_infer_shape.py
浏览文件 @
a3911ab5
...
@@ -494,6 +494,11 @@ class SymbolicShapeInference:
...
@@ -494,6 +494,11 @@ class SymbolicShapeInference:
# contrib ops
# contrib ops
'Attention'
,
'BiasGelu'
,
\
'Attention'
,
'BiasGelu'
,
\
'EmbedLayerNormalization'
,
\
'EmbedLayerNormalization'
,
\
'FastGelu'
,
'Gelu'
,
'LayerNormalization'
,
\
'FastGelu'
,
'Gelu'
,
'LayerNormalization'
,
\
...
...
tools/setup_helpers/__init__.py
浏览文件 @
a3911ab5
from
.extension
import
*
from
.extension
import
*
\ No newline at end of file
tools/setup_helpers/extension.py
浏览文件 @
a3911ab5
import
distutils.sysconfig
import
os
import
os
import
platform
import
platform
import
subprocess
import
subprocess
from
pathlib
import
Path
from
pathlib
import
Path
import
distutils.sysconfig
from
setuptools
import
Extension
from
setuptools
import
Extension
from
setuptools.command.build_ext
import
build_ext
from
setuptools.command.build_ext
import
build_ext
...
@@ -27,11 +27,13 @@ def _get_build(var, default=False):
...
@@ -27,11 +27,13 @@ def _get_build(var, default=False):
if
val
in
trues
:
if
val
in
trues
:
return
True
return
True
if
val
not
in
falses
:
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
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_MAD
=
_get_build
(
"BUILD_MAD"
,
False
)
# _BUILD_KALDI = False if platform.system() == "Windows" else _get_build("BUILD_KALDI", True)
# _BUILD_KALDI = False if platform.system() == "Windows" else _get_build("BUILD_KALDI", True)
# _BUILD_RNNT = _get_build("BUILD_RNNT", True)
# _BUILD_RNNT = _get_build("BUILD_RNNT", True)
...
@@ -40,7 +42,8 @@ _BUILD_MAD = _get_build("BUILD_MAD", False)
...
@@ -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_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_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()
# _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
():
def
get_ext_modules
():
...
@@ -71,7 +74,8 @@ class CMakeBuild(build_ext):
...
@@ -71,7 +74,8 @@ class CMakeBuild(build_ext):
if
ext
.
name
!=
"paddlespeech.audio._paddleaudio"
:
if
ext
.
name
!=
"paddlespeech.audio._paddleaudio"
:
return
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
# required for auto-detection of auxiliary "native" libs
if
not
extdir
.
endswith
(
os
.
path
.
sep
):
if
not
extdir
.
endswith
(
os
.
path
.
sep
):
...
@@ -101,8 +105,12 @@ class CMakeBuild(build_ext):
...
@@ -101,8 +105,12 @@ class CMakeBuild(build_ext):
if
_PADDLESPEECH_CUDA_ARCH_LIST
is
not
None
:
if
_PADDLESPEECH_CUDA_ARCH_LIST
is
not
None
:
# Convert MAJOR.MINOR[+PTX] list to new style one
# Convert MAJOR.MINOR[+PTX] list to new style one
# defined at https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html
# defined at https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html
_arches
=
_PADDLESPEECH_CUDA_ARCH_LIST
.
replace
(
"."
,
""
).
replace
(
" "
,
";"
).
split
(
";"
)
_arches
=
_PADDLESPEECH_CUDA_ARCH_LIST
.
replace
(
"."
,
""
).
replace
(
_arches
=
[
arch
[:
-
4
]
if
arch
.
endswith
(
"+PTX"
)
else
f
"
{
arch
}
-real"
for
arch
in
_arches
]
" "
,
";"
).
split
(
";"
)
_arches
=
[
arch
[:
-
4
]
if
arch
.
endswith
(
"+PTX"
)
else
f
"
{
arch
}
-real"
for
arch
in
_arches
]
cmake_args
+=
[
f
"-DCMAKE_CUDA_ARCHITECTURES=
{
';'
.
join
(
_arches
)
}
"
]
cmake_args
+=
[
f
"-DCMAKE_CUDA_ARCHITECTURES=
{
';'
.
join
(
_arches
)
}
"
]
# Default to Ninja
# Default to Ninja
...
@@ -131,10 +139,13 @@ class CMakeBuild(build_ext):
...
@@ -131,10 +139,13 @@ class CMakeBuild(build_ext):
if
not
os
.
path
.
exists
(
self
.
build_temp
):
if
not
os
.
path
.
exists
(
self
.
build_temp
):
os
.
makedirs
(
self
.
build_temp
)
os
.
makedirs
(
self
.
build_temp
)
print
(
f
"cmake
{
_ROOT_DIR
}
{
' '
.
join
(
cmake_args
)
}
, cwd=
{
self
.
build_temp
}
"
)
print
(
subprocess
.
check_call
([
"cmake"
,
str
(
_ROOT_DIR
)]
+
cmake_args
,
cwd
=
self
.
build_temp
)
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
}
"
)
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
):
def
get_ext_filename
(
self
,
fullname
):
ext_filename
=
super
().
get_ext_filename
(
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录