Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
spdlog
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
spdlog
Commits
f3662255
Commit
f3662255
authored
Nov 05, 2015
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated cppformat lib
parent
f15ed237
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
206 additions
and
52 deletions
+206
-52
include/spdlog/details/format.cc
include/spdlog/details/format.cc
+24
-12
include/spdlog/details/format.h
include/spdlog/details/format.h
+182
-40
No files found.
include/spdlog/details/format.cc
View file @
f3662255
...
...
@@ -52,10 +52,10 @@
using
fmt
::
internal
::
Arg
;
// Check if exceptions are disabled.
#if
__GNUC__ && !__EXCEPTIONS
#if
defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
#endif
#if
_MSC_VER
&& !_HAS_EXCEPTIONS
#if
defined(_MSC_VER)
&& !_HAS_EXCEPTIONS
# define FMT_EXCEPTIONS 0
#endif
#ifndef FMT_EXCEPTIONS
...
...
@@ -84,7 +84,7 @@ using fmt::internal::Arg;
# define FMT_FUNC
#endif
#if _MSC_VER
#if
def
_MSC_VER
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4702) // unreachable code
...
...
@@ -142,6 +142,7 @@ struct IntChecker<true> {
static
bool
fits_in_int
(
T
value
)
{
return
value
>=
INT_MIN
&&
value
<=
INT_MAX
;
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
const
char
RESET_COLOR
[]
=
"
\x1b
[0m"
;
...
...
@@ -443,18 +444,20 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
typedef
typename
BasicWriter
<
Char
>::
CharPtr
CharPtr
;
Char
fill
=
internal
::
CharTraits
<
Char
>::
cast
(
spec_
.
fill
());
CharPtr
out
=
CharPtr
();
if
(
spec_
.
width_
>
1
)
{
const
unsigned
CHAR_WIDTH
=
1
;
if
(
spec_
.
width_
>
CHAR_WIDTH
)
{
out
=
writer_
.
grow_buffer
(
spec_
.
width_
);
if
(
spec_
.
align_
==
ALIGN_RIGHT
)
{
std
::
fill_n
(
out
,
spec_
.
width_
-
1
,
fill
);
out
+=
spec_
.
width_
-
1
;
std
::
fill_n
(
out
,
spec_
.
width_
-
CHAR_WIDTH
,
fill
);
out
+=
spec_
.
width_
-
CHAR_WIDTH
;
}
else
if
(
spec_
.
align_
==
ALIGN_CENTER
)
{
out
=
writer_
.
fill_padding
(
out
,
spec_
.
width_
,
1
,
fill
);
out
=
writer_
.
fill_padding
(
out
,
spec_
.
width_
,
internal
::
check
(
CHAR_WIDTH
),
fill
);
}
else
{
std
::
fill_n
(
out
+
1
,
spec_
.
width_
-
1
,
fill
);
std
::
fill_n
(
out
+
CHAR_WIDTH
,
spec_
.
width_
-
CHAR_WIDTH
,
fill
);
}
}
else
{
out
=
writer_
.
grow_buffer
(
1
);
out
=
writer_
.
grow_buffer
(
CHAR_WIDTH
);
}
*
out
=
internal
::
CharTraits
<
Char
>::
cast
(
value
);
}
...
...
@@ -523,6 +526,13 @@ class PrintfArgFormatter :
}
*
out
=
static_cast
<
Char
>
(
value
);
}
void
visit_custom
(
Arg
::
CustomValue
c
)
{
BasicFormatter
<
Char
>
formatter
(
ArgList
(),
this
->
writer
());
const
Char
format_str
[]
=
{
'}'
,
0
};
const
Char
*
format
=
format_str
;
c
.
format
(
&
formatter
,
c
.
value
,
&
format
);
}
};
}
// namespace internal
}
// namespace fmt
...
...
@@ -773,8 +783,10 @@ void fmt::BasicWriter<Char>::write_str(
const
StrChar
*
str_value
=
s
.
value
;
std
::
size_t
str_size
=
s
.
size
;
if
(
str_size
==
0
)
{
if
(
!
str_value
)
if
(
!
str_value
)
{
FMT_THROW
(
FormatError
(
"string pointer is null"
));
return
;
}
if
(
*
str_value
)
str_size
=
std
::
char_traits
<
StrChar
>::
length
(
str_value
);
}
...
...
@@ -1253,7 +1265,7 @@ FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args)
FMT_FUNC
void
fmt
::
print_colored
(
Color
c
,
CStringRef
format
,
ArgList
args
)
{
char
escape
[]
=
"
\x1b
[30m"
;
escape
[
3
]
=
'0'
+
static_cast
<
char
>
(
c
);
escape
[
3
]
=
static_cast
<
char
>
(
'0'
+
c
);
std
::
fputs
(
escape
,
stdout
);
print
(
format
,
args
);
std
::
fputs
(
RESET_COLOR
,
stdout
);
...
...
@@ -1313,6 +1325,6 @@ template int fmt::internal::CharTraits<wchar_t>::format_float(
#endif // FMT_HEADER_ONLY
#if _MSC_VER
#if
def
_MSC_VER
# pragma warning(pop)
#endif
\ No newline at end of file
include/spdlog/details/format.h
View file @
f3662255
...
...
@@ -39,10 +39,23 @@
#include <limits>
#include <stdexcept>
#include <string>
#include <sstream>
#include <map>
#if _SECURE_SCL
#ifndef FMT_USE_IOSTREAMS
# define FMT_USE_IOSTREAMS 1
#endif
#if FMT_USE_IOSTREAMS
# include <sstream>
#endif
#ifdef _SECURE_SCL
# define FMT_SECURE_SCL _SECURE_SCL
#else
# define FMT_SECURE_SCL 0
#endif
#if FMT_SECURE_SCL
# include <iterator>
#endif
...
...
@@ -93,6 +106,9 @@ inline uint32_t clzll(uint64_t x) {
// Disable the warning about declaration shadowing because it affects too
// many valid cases.
# pragma GCC diagnostic ignored "-Wshadow"
// Disable the warning about implicit conversions that may change the sign of
// an integer; silencing it otherwise would require many explicit casts.
# pragma GCC diagnostic ignored "-Wsign-conversion"
# endif
# if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__
# define FMT_HAS_GXX_CXX11 1
...
...
@@ -154,9 +170,14 @@ inline uint32_t clzll(uint64_t x) {
#endif
// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
#ifndef FMT_USE_NOEXCEPT
# define FMT_USE_NOEXCEPT 0
#endif
#ifndef FMT_NOEXCEPT
# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11)
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
_MSC_VER >= 1900
# define FMT_NOEXCEPT noexcept
# else
# define FMT_NOEXCEPT throw()
...
...
@@ -165,6 +186,10 @@ inline uint32_t clzll(uint64_t x) {
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#ifndef FMT_USE_DELETED_FUNCTIONS
# define FMT_USE_DELETED_FUNCTIONS 0
#endif
#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
(FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800
# define FMT_DELETED_OR_UNDEFINED = delete
...
...
@@ -178,6 +203,16 @@ inline uint32_t clzll(uint64_t x) {
TypeName& operator=(const TypeName&)
#endif
#ifndef FMT_USE_USER_DEFINED_LITERALS
// All compilers which support UDLs also support variadic templates. This
// makes the fmt::literals implementation easier. However, an explicit check
// for variadic templates is added here just in case.
# define FMT_USE_USER_DEFINED_LITERALS \
FMT_USE_VARIADIC_TEMPLATES && \
(FMT_HAS_FEATURE(cxx_user_literals) || \
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900)
#endif
#ifndef FMT_ASSERT
# define FMT_ASSERT(condition, message) assert((condition) && message)
#endif
...
...
@@ -271,22 +306,38 @@ class BasicStringRef {
/** Returns the string size. */
std
::
size_t
size
()
const
{
return
size_
;
}
// Lexicographically compare this string reference to other.
int
compare
(
BasicStringRef
other
)
const
{
std
::
size_t
size
=
std
::
min
(
size_
,
other
.
size_
);
int
result
=
std
::
char_traits
<
Char
>::
compare
(
data_
,
other
.
data_
,
size
);
if
(
result
==
0
)
result
=
size_
==
other
.
size_
?
0
:
(
size_
<
other
.
size_
?
-
1
:
1
);
return
result
;
}
friend
bool
operator
==
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
data_
==
rhs
.
data_
;
return
lhs
.
compare
(
rhs
)
==
0
;
}
friend
bool
operator
!=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
data_
!=
rhs
.
data_
;
return
lhs
.
compare
(
rhs
)
!=
0
;
}
friend
bool
operator
<
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
std
::
lexicographical_compare
(
lhs
.
data_
,
lhs
.
data_
+
lhs
.
size_
,
rhs
.
data_
,
rhs
.
data_
+
rhs
.
size_
);
return
lhs
.
compare
(
rhs
)
<
0
;
}
friend
bool
operator
<=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
<=
0
;
}
friend
bool
operator
>
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
>
0
;
}
friend
bool
operator
>=
(
BasicStringRef
lhs
,
BasicStringRef
rhs
)
{
return
lhs
.
compare
(
rhs
)
>=
0
;
}
};
typedef
BasicStringRef
<
char
>
StringRef
;
typedef
BasicStringRef
<
wchar_t
>
WStringRef
;
/**
\rst
A reference to a null terminated string. It can be constructed from a C
...
...
@@ -349,7 +400,7 @@ namespace internal {
// to avoid dynamic memory allocation.
enum
{
INLINE_BUFFER_SIZE
=
500
};
#if _SECURE_SCL
#if
FMT
_SECURE_SCL
// Use checked iterator to avoid warnings on MSVC.
template
<
typename
T
>
inline
stdext
::
checked_array_iterator
<
T
*>
make_ptr
(
T
*
ptr
,
std
::
size_t
size
)
{
...
...
@@ -450,9 +501,9 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
private:
T
data_
[
SIZE
];
//
Fre
e memory allocated by the buffer.
void
fre
e
()
{
if
(
this
->
ptr_
!=
data_
)
this
->
deallocate
(
this
->
ptr_
,
this
->
capacity_
);
//
Deallocat
e memory allocated by the buffer.
void
deallocat
e
()
{
if
(
this
->
ptr_
!=
data_
)
Allocator
::
deallocate
(
this
->
ptr_
,
this
->
capacity_
);
}
protected:
...
...
@@ -461,7 +512,7 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
public:
explicit
MemoryBuffer
(
const
Allocator
&
alloc
=
Allocator
())
:
Allocator
(
alloc
),
Buffer
<
T
>
(
data_
,
SIZE
)
{}
~
MemoryBuffer
()
{
fre
e
();
}
~
MemoryBuffer
()
{
deallocat
e
();
}
#if FMT_USE_RVALUE_REFERENCES
private:
...
...
@@ -478,7 +529,7 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
}
else
{
this
->
ptr_
=
other
.
ptr_
;
// Set pointer to the inline array so that delete is not called
// when
free
ing.
// when
deallocat
ing.
other
.
ptr_
=
other
.
data_
;
}
}
...
...
@@ -490,7 +541,7 @@ class MemoryBuffer : private Allocator, public Buffer<T> {
MemoryBuffer
&
operator
=
(
MemoryBuffer
&&
other
)
{
assert
(
this
!=
&
other
);
fre
e
();
deallocat
e
();
move
(
other
);
return
*
this
;
}
...
...
@@ -516,7 +567,7 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
// the buffer already uses the new storage and will deallocate it in case
// of exception.
if
(
old_ptr
!=
data_
)
this
->
deallocate
(
old_ptr
,
old_capacity
);
Allocator
::
deallocate
(
old_ptr
,
old_capacity
);
}
// A fixed-size buffer.
...
...
@@ -549,6 +600,15 @@ inline int isinfinity(long double x) { return isinf(x); }
inline
int
isinfinity
(
double
x
)
{
return
std
::
isinf
(
x
);
}
inline
int
isinfinity
(
long
double
x
)
{
return
std
::
isinf
(
x
);
}
# endif
// Portable version of isnan.
# ifdef isnan
inline
int
isnotanumber
(
double
x
)
{
return
isnan
(
x
);
}
inline
int
isnotanumber
(
long
double
x
)
{
return
isnan
(
x
);
}
# else
inline
int
isnotanumber
(
double
x
)
{
return
std
::
isnan
(
x
);
}
inline
int
isnotanumber
(
long
double
x
)
{
return
std
::
isnan
(
x
);
}
# endif
#else
inline
int
getsign
(
double
value
)
{
if
(
value
<
0
)
return
1
;
...
...
@@ -562,12 +622,16 @@ inline int isinfinity(double x) { return !_finite(x); }
inline
int
isinfinity
(
long
double
x
)
{
return
!
_finite
(
static_cast
<
double
>
(
x
));
}
inline
int
isnotanumber
(
double
x
)
{
return
_isnan
(
x
);
}
inline
int
isnotanumber
(
long
double
x
)
{
return
_isnan
(
static_cast
<
double
>
(
x
));
}
#endif
template
<
typename
Char
>
class
BasicCharTraits
{
public:
#if _SECURE_SCL
#if
FMT
_SECURE_SCL
typedef
stdext
::
checked_array_iterator
<
Char
*>
CharPtr
;
#else
typedef
Char
*
CharPtr
;
...
...
@@ -718,7 +782,7 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
// Integer division is slow so do it for a group of two digits instead
// of for every digit. The idea comes from the talk by Alexandrescu
// "Three Optimization Tips for C++". See speed-test for a comparison.
unsigned
index
=
(
value
%
100
)
*
2
;
unsigned
index
=
static_cast
<
unsigned
>
((
value
%
100
)
*
2
)
;
value
/=
100
;
*--
buffer
=
Data
::
DIGITS
[
index
+
1
];
*--
buffer
=
Data
::
DIGITS
[
index
];
...
...
@@ -851,7 +915,7 @@ struct WCharHelper<T, wchar_t> {
template
<
typename
T
>
class
IsConvertibleToInt
{
pr
ivate
:
pr
otected
:
typedef
char
yes
[
1
];
typedef
char
no
[
2
];
...
...
@@ -890,7 +954,8 @@ struct Conditional<false, T, F> { typedef F type; };
// A helper function to suppress bogus "conditional expression is constant"
// warnings.
inline
bool
check
(
bool
value
)
{
return
value
;
}
template
<
typename
T
>
inline
T
check
(
T
value
)
{
return
value
;
}
// Makes an Arg object from any type.
template
<
typename
Char
>
...
...
@@ -910,7 +975,9 @@ class MakeValue : public Arg {
// characters and strings into narrow strings as in
// fmt::format("{}", L"test");
// To fix this, use a wide format string: fmt::format(L"{}", L"test").
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
MakeValue
(
typename
WCharHelper
<
wchar_t
,
Char
>::
Unsupported
);
#endif
MakeValue
(
typename
WCharHelper
<
wchar_t
*
,
Char
>::
Unsupported
);
MakeValue
(
typename
WCharHelper
<
const
wchar_t
*
,
Char
>::
Unsupported
);
MakeValue
(
typename
WCharHelper
<
const
std
::
wstring
&
,
Char
>::
Unsupported
);
...
...
@@ -983,10 +1050,12 @@ class MakeValue : public Arg {
FMT_MAKE_VALUE
(
unsigned
char
,
int_value
,
CHAR
)
FMT_MAKE_VALUE
(
char
,
int_value
,
CHAR
)
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
MakeValue
(
typename
WCharHelper
<
wchar_t
,
Char
>::
Supported
value
)
{
int_value
=
value
;
}
static
uint64_t
type
(
wchar_t
)
{
return
Arg
::
CHAR
;
}
#endif
#define FMT_MAKE_STR_VALUE(Type, TYPE) \
MakeValue(Type value) { set_string(value); } \
...
...
@@ -1047,7 +1116,7 @@ struct NamedArg : Arg {
template
<
typename
T
>
NamedArg
(
BasicStringRef
<
Char
>
argname
,
const
T
&
value
)
:
name
(
argname
),
Arg
(
MakeValue
<
Char
>
(
value
)
)
{
:
Arg
(
MakeValue
<
Char
>
(
value
)),
name
(
argname
)
{
type
=
static_cast
<
internal
::
Arg
::
Type
>
(
MakeValue
<
Char
>::
type
(
value
));
}
};
...
...
@@ -1847,7 +1916,7 @@ class BasicWriter {
typedef
typename
internal
::
CharTraits
<
Char
>::
CharPtr
CharPtr
;
#if _SECURE_SCL
#if
FMT
_SECURE_SCL
// Returns pointer value.
static
Char
*
get
(
CharPtr
p
)
{
return
p
.
base
();
}
#else
...
...
@@ -2265,7 +2334,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
Char
*
p
=
get
(
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
));
n
=
abs_value
;
do
{
*
p
--
=
'0'
+
(
n
&
1
);
*
p
--
=
static_cast
<
Char
>
(
'0'
+
(
n
&
1
)
);
}
while
((
n
>>=
1
)
!=
0
);
break
;
}
...
...
@@ -2280,7 +2349,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
Char
*
p
=
get
(
prepare_int_buffer
(
num_digits
,
spec
,
prefix
,
prefix_size
));
n
=
abs_value
;
do
{
*
p
--
=
'0'
+
(
n
&
7
);
*
p
--
=
static_cast
<
Char
>
(
'0'
+
(
n
&
7
)
);
}
while
((
n
>>=
3
)
!=
0
);
break
;
}
...
...
@@ -2328,7 +2397,7 @@ void BasicWriter<Char>::write_double(
sign
=
spec
.
flag
(
PLUS_FLAG
)
?
'+'
:
' '
;
}
if
(
value
!=
value
)
{
if
(
internal
::
isnotanumber
(
value
)
)
{
// Format NaN ourselves because sprintf's output is not consistent
// across platforms.
std
::
size_t
nan_size
=
4
;
...
...
@@ -2396,7 +2465,7 @@ void BasicWriter<Char>::write_double(
Char
fill
=
internal
::
CharTraits
<
Char
>::
cast
(
spec
.
fill
());
for
(;;)
{
std
::
size_t
buffer_size
=
buffer_
.
capacity
()
-
offset
;
#if _MSC_VER
#if
def
_MSC_VER
// MSVC's vsnprintf_s doesn't work with zero size, so reserve
// space for at least one extra character to make the size non-zero.
// Note that the buffer's capacity will increase by more than 1.
...
...
@@ -2677,17 +2746,6 @@ void print(std::FILE *f, CStringRef format_str, ArgList args);
*/
void
print
(
CStringRef
format_str
,
ArgList
args
);
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
template
<
typename
Char
>
void
printf
(
BasicWriter
<
Char
>
&
w
,
BasicCStringRef
<
Char
>
format
,
ArgList
args
)
{
internal
::
PrintfFormatter
<
Char
>
(
args
).
format
(
w
,
format
);
...
...
@@ -2708,6 +2766,12 @@ inline std::string sprintf(CStringRef format, ArgList args) {
return
w
.
str
();
}
inline
std
::
wstring
sprintf
(
WCStringRef
format
,
ArgList
args
)
{
WMemoryWriter
w
;
printf
(
w
,
format
,
args
);
return
w
.
str
();
}
/**
\rst
Prints formatted data to the file *f*.
...
...
@@ -2750,7 +2814,7 @@ class FormatInt {
// Integer division is slow so do it for a group of two digits instead
// of for every digit. The idea comes from the talk by Alexandrescu
// "Three Optimization Tips for C++". See speed-test for a comparison.
unsigned
index
=
(
value
%
100
)
*
2
;
unsigned
index
=
static_cast
<
unsigned
>
((
value
%
100
)
*
2
)
;
value
/=
100
;
*--
buffer_end
=
internal
::
Data
::
DIGITS
[
index
+
1
];
*--
buffer_end
=
internal
::
Data
::
DIGITS
[
index
];
...
...
@@ -2993,12 +3057,90 @@ FMT_VARIADIC(std::string, format, CStringRef)
FMT_VARIADIC_W
(
std
::
wstring
,
format
,
WCStringRef
)
FMT_VARIADIC
(
void
,
print
,
CStringRef
)
FMT_VARIADIC
(
void
,
print
,
std
::
FILE
*
,
CStringRef
)
FMT_VARIADIC
(
void
,
print
,
std
::
ostream
&
,
CStringRef
)
FMT_VARIADIC
(
void
,
print_colored
,
Color
,
CStringRef
)
FMT_VARIADIC
(
std
::
string
,
sprintf
,
CStringRef
)
FMT_VARIADIC_W
(
std
::
wstring
,
sprintf
,
WCStringRef
)
FMT_VARIADIC
(
int
,
printf
,
CStringRef
)
FMT_VARIADIC
(
int
,
fprintf
,
std
::
FILE
*
,
CStringRef
)
}
#if FMT_USE_IOSTREAMS
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
FMT_VARIADIC
(
void
,
print
,
std
::
ostream
&
,
CStringRef
)
#endif
}
// namespace fmt
#if FMT_USE_USER_DEFINED_LITERALS
namespace
fmt
{
namespace
internal
{
template
<
typename
Char
>
struct
UdlFormat
{
const
Char
*
str
;
template
<
typename
...
Args
>
auto
operator
()(
Args
&&
...
args
)
const
->
decltype
(
format
(
str
,
std
::
forward
<
Args
>
(
args
)...))
{
return
format
(
str
,
std
::
forward
<
Args
>
(
args
)...);
}
};
template
<
typename
Char
>
struct
UdlArg
{
const
Char
*
str
;
template
<
typename
T
>
NamedArg
<
Char
>
operator
=
(
T
&&
value
)
const
{
return
{
str
,
std
::
forward
<
T
>
(
value
)};
}
};
}
// namespace internal
inline
namespace
literals
{
/**
\rst
C++11 literal equivalent of :func:`fmt::format`.
**Example**::
using namespace fmt::literals;
std::string message = "The answer is {}"_format(42);
\endrst
*/
inline
internal
::
UdlFormat
<
char
>
operator
""
_format
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
inline
internal
::
UdlFormat
<
wchar_t
>
operator
""
_format
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
/**
\rst
C++11 literal equivalent of :func:`fmt::arg`.
**Example**::
using namespace fmt::literals;
print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
\endrst
*/
inline
internal
::
UdlArg
<
char
>
operator
""
_a
(
const
char
*
s
,
std
::
size_t
)
{
return
{
s
};
}
inline
internal
::
UdlArg
<
wchar_t
>
operator
""
_a
(
const
wchar_t
*
s
,
std
::
size_t
)
{
return
{
s
};
}
}
// inline namespace literals
}
// namespace fmt
#endif // FMT_USE_USER_DEFINED_LITERALS
// Restore warnings.
#if FMT_GCC_VERSION >= 406
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment