Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
9227a0f3
Commit
9227a0f3
authored
Jun 06, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Eliminate RemoveReference -- all uses turned out to be unnecessary or outright wrong.
parent
2fc62718
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
41 additions
and
60 deletions
+41
-60
dynamic.c++
c++/src/capnproto/dynamic.c++
+4
-4
dynamic.h
c++/src/capnproto/dynamic.h
+1
-1
list.h
c++/src/capnproto/list.h
+3
-3
schema.c++
c++/src/capnproto/schema.c++
+1
-1
array.h
c++/src/kj/array.h
+3
-3
common-test.c++
c++/src/kj/common-test.c++
+13
-8
common.h
c++/src/kj/common.h
+15
-39
memory.h
c++/src/kj/memory.h
+1
-1
No files found.
c++/src/capnproto/dynamic.c++
View file @
9227a0f3
...
@@ -1431,13 +1431,13 @@ typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \
...
@@ -1431,13 +1431,13 @@ typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \
HANDLE_NUMERIC_TYPE
(
int8_t
,
checkRoundTrip
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
int8_t
,
checkRoundTrip
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
int16_t
,
checkRoundTrip
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
int16_t
,
checkRoundTrip
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
int32_t
,
checkRoundTrip
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
int32_t
,
checkRoundTrip
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
int64_t
,
kj
::
upc
ast
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
int64_t
,
kj
::
implicitC
ast
,
unsignedToSigned
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint8_t
,
signedToUnsigned
,
checkRoundTrip
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint8_t
,
signedToUnsigned
,
checkRoundTrip
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint16_t
,
signedToUnsigned
,
checkRoundTrip
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint16_t
,
signedToUnsigned
,
checkRoundTrip
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint32_t
,
signedToUnsigned
,
checkRoundTrip
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint32_t
,
signedToUnsigned
,
checkRoundTrip
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint64_t
,
signedToUnsigned
,
kj
::
upc
ast
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
uint64_t
,
signedToUnsigned
,
kj
::
implicitC
ast
,
checkRoundTrip
)
HANDLE_NUMERIC_TYPE
(
float
,
kj
::
upcast
,
kj
::
upcast
,
kj
::
upc
ast
)
HANDLE_NUMERIC_TYPE
(
float
,
kj
::
implicitCast
,
kj
::
implicitCast
,
kj
::
implicitC
ast
)
HANDLE_NUMERIC_TYPE
(
double
,
kj
::
upcast
,
kj
::
upcast
,
kj
::
upc
ast
)
HANDLE_NUMERIC_TYPE
(
double
,
kj
::
implicitCast
,
kj
::
implicitCast
,
kj
::
implicitC
ast
)
#undef HANDLE_NUMERIC_TYPE
#undef HANDLE_NUMERIC_TYPE
...
...
c++/src/capnproto/dynamic.h
View file @
9227a0f3
...
@@ -743,7 +743,7 @@ BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) {
...
@@ -743,7 +743,7 @@ BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) {
}
}
template
<
typename
T
>
template
<
typename
T
>
DynamicTypeFor
<
TypeIfEnum
<
T
>>
toDynamic
(
T
&&
value
)
{
DynamicTypeFor
<
TypeIfEnum
<
T
>>
toDynamic
(
T
&&
value
)
{
return
DynamicEnum
(
Schema
::
from
<
kj
::
RemoveReference
<
T
>>
(),
static_cast
<
uint16_t
>
(
value
));
return
DynamicEnum
(
Schema
::
from
<
kj
::
Decay
<
T
>>
(),
static_cast
<
uint16_t
>
(
value
));
}
}
inline
DynamicValue
::
Reader
::
Reader
(
std
::
nullptr_t
n
)
:
type
(
UNKNOWN
)
{}
inline
DynamicValue
::
Reader
::
Reader
(
std
::
nullptr_t
n
)
:
type
(
UNKNOWN
)
{}
...
...
c++/src/capnproto/list.h
View file @
9227a0f3
...
@@ -63,18 +63,18 @@ using BuilderFor = typename internal::MaybeReaderBuilder<T>::Builder;
...
@@ -63,18 +63,18 @@ using BuilderFor = typename internal::MaybeReaderBuilder<T>::Builder;
// The type returned by List<T>::Builder::operator[].
// The type returned by List<T>::Builder::operator[].
template
<
typename
T
>
template
<
typename
T
>
using
FromReader
=
typename
kj
::
RemoveReference
<
T
>::
Reads
;
using
FromReader
=
typename
kj
::
Decay
<
T
>::
Reads
;
// FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).
// FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).
template
<
typename
T
>
template
<
typename
T
>
using
FromBuilder
=
typename
kj
::
RemoveReference
<
T
>::
Builds
;
using
FromBuilder
=
typename
kj
::
Decay
<
T
>::
Builds
;
// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
template
<
typename
T
,
Kind
k
=
kind
<
T
>
()
>
struct
TypeIfEnum_
;
template
<
typename
T
,
Kind
k
=
kind
<
T
>
()
>
struct
TypeIfEnum_
;
template
<
typename
T
>
struct
TypeIfEnum_
<
T
,
Kind
::
ENUM
>
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
TypeIfEnum_
<
T
,
Kind
::
ENUM
>
{
typedef
T
Type
;
};
template
<
typename
T
>
template
<
typename
T
>
using
TypeIfEnum
=
typename
TypeIfEnum_
<
kj
::
RemoveReference
<
T
>>::
Type
;
using
TypeIfEnum
=
typename
TypeIfEnum_
<
kj
::
Decay
<
T
>>::
Type
;
namespace
internal
{
namespace
internal
{
...
...
c++/src/capnproto/schema.c++
View file @
9227a0f3
...
@@ -88,7 +88,7 @@ namespace {
...
@@ -88,7 +88,7 @@ namespace {
template
<
typename
List
>
template
<
typename
List
>
auto
findSchemaMemberByName
(
const
internal
::
RawSchema
*
raw
,
kj
::
StringPtr
name
,
auto
findSchemaMemberByName
(
const
internal
::
RawSchema
*
raw
,
kj
::
StringPtr
name
,
uint
unionIndex
,
List
&&
list
)
uint
unionIndex
,
List
&&
list
)
->
kj
::
Maybe
<
kj
::
RemoveReference
<
decltype
(
list
[
0
])
>>
{
->
kj
::
Maybe
<
kj
::
Decay
<
decltype
(
list
[
0
])
>>
{
uint
lower
=
0
;
uint
lower
=
0
;
uint
upper
=
raw
->
memberCount
;
uint
upper
=
raw
->
memberCount
;
...
...
c++/src/kj/array.h
View file @
9227a0f3
...
@@ -517,14 +517,14 @@ struct CopyConstructArray_<T, Iterator, false> {
...
@@ -517,14 +517,14 @@ struct CopyConstructArray_<T, Iterator, false> {
static
T
*
apply
(
T
*
__restrict__
pos
,
Iterator
start
,
Iterator
end
)
{
static
T
*
apply
(
T
*
__restrict__
pos
,
Iterator
start
,
Iterator
end
)
{
if
(
noexcept
(
T
(
instance
<
const
T
&>
())))
{
if
(
noexcept
(
T
(
instance
<
const
T
&>
())))
{
while
(
start
!=
end
)
{
while
(
start
!=
end
)
{
ctor
(
*
pos
++
,
upc
ast
<
const
T
&>
(
*
start
++
));
ctor
(
*
pos
++
,
implicitC
ast
<
const
T
&>
(
*
start
++
));
}
}
return
pos
;
return
pos
;
}
else
{
}
else
{
// Crap. This is complicated.
// Crap. This is complicated.
ExceptionGuard
guard
(
pos
);
ExceptionGuard
guard
(
pos
);
while
(
start
!=
end
)
{
while
(
start
!=
end
)
{
ctor
(
*
guard
.
pos
,
upc
ast
<
const
T
&>
(
*
start
++
));
ctor
(
*
guard
.
pos
,
implicitC
ast
<
const
T
&>
(
*
start
++
));
++
guard
.
pos
;
++
guard
.
pos
;
}
}
guard
.
start
=
guard
.
pos
;
guard
.
start
=
guard
.
pos
;
...
@@ -535,7 +535,7 @@ struct CopyConstructArray_<T, Iterator, false> {
...
@@ -535,7 +535,7 @@ struct CopyConstructArray_<T, Iterator, false> {
template
<
typename
T
,
typename
Iterator
>
template
<
typename
T
,
typename
Iterator
>
inline
T
*
copyConstructArray
(
T
*
dst
,
Iterator
start
,
Iterator
end
)
{
inline
T
*
copyConstructArray
(
T
*
dst
,
Iterator
start
,
Iterator
end
)
{
return
CopyConstructArray_
<
T
,
RemoveReference
<
Iterator
>>::
apply
(
dst
,
start
,
end
);
return
CopyConstructArray_
<
T
,
Decay
<
Iterator
>>::
apply
(
dst
,
start
,
end
);
}
}
}
// namespace internal
}
// namespace internal
...
...
c++/src/kj/common-test.c++
View file @
9227a0f3
...
@@ -106,7 +106,7 @@ TEST(Common, Maybe) {
...
@@ -106,7 +106,7 @@ TEST(Common, Maybe) {
}
}
{
{
Maybe
<
int
&>
m
=
upc
ast
<
int
*>
(
nullptr
);
Maybe
<
int
&>
m
=
implicitC
ast
<
int
*>
(
nullptr
);
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
KJ_IF_MAYBE
(
v
,
m
)
{
...
@@ -138,7 +138,7 @@ TEST(Common, Maybe) {
...
@@ -138,7 +138,7 @@ TEST(Common, Maybe) {
}
}
{
{
Maybe
<
int
>
m
=
upc
ast
<
int
*>
(
nullptr
);
Maybe
<
int
>
m
=
implicitC
ast
<
int
*>
(
nullptr
);
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
KJ_IF_MAYBE
(
v
,
m
)
{
...
@@ -171,16 +171,23 @@ TEST(Common, MaybeConstness) {
...
@@ -171,16 +171,23 @@ TEST(Common, MaybeConstness) {
class
Foo
{
class
Foo
{
public
:
public
:
KJ_DISALLOW_COPY
(
Foo
);
virtual
~
Foo
()
{}
virtual
~
Foo
()
{}
protected
:
Foo
()
=
default
;
};
};
class
Bar
:
public
Foo
{
class
Bar
:
public
Foo
{
public
:
public
:
Bar
()
=
default
;
KJ_DISALLOW_COPY
(
Bar
);
virtual
~
Bar
()
{}
virtual
~
Bar
()
{}
};
};
class
Baz
:
public
Foo
{
class
Baz
:
public
Foo
{
public
:
public
:
Baz
()
=
delete
;
KJ_DISALLOW_COPY
(
Baz
);
virtual
~
Baz
()
{}
virtual
~
Baz
()
{}
};
};
...
@@ -188,23 +195,21 @@ TEST(Common, Downcast) {
...
@@ -188,23 +195,21 @@ TEST(Common, Downcast) {
Bar
bar
;
Bar
bar
;
Foo
&
foo
=
bar
;
Foo
&
foo
=
bar
;
EXPECT_EQ
(
&
bar
,
&
downcast
<
Bar
&>
(
foo
));
EXPECT_EQ
(
&
bar
,
&
downcast
<
Bar
>
(
foo
));
EXPECT_EQ
(
&
bar
,
downcast
<
Bar
*>
(
&
foo
));
#if !defined(NDEBUG) && !KJ_NO_RTTI
#if !defined(NDEBUG) && !KJ_NO_RTTI
EXPECT_ANY_THROW
(
downcast
<
Baz
&>
(
foo
));
EXPECT_ANY_THROW
(
downcast
<
Baz
>
(
foo
));
EXPECT_ANY_THROW
(
downcast
<
Baz
*>
(
&
foo
));
#endif
#endif
#if KJ_NO_RTTI
#if KJ_NO_RTTI
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Bar
&>
(
foo
)
==
nullptr
);
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Bar
&>
(
foo
)
==
nullptr
);
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Baz
&>
(
foo
)
==
nullptr
);
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Baz
&>
(
foo
)
==
nullptr
);
#else
#else
KJ_IF_MAYBE
(
m
,
dynamicDowncastIfAvailable
<
Bar
&
>
(
foo
))
{
KJ_IF_MAYBE
(
m
,
dynamicDowncastIfAvailable
<
Bar
>
(
foo
))
{
EXPECT_EQ
(
&
bar
,
m
);
EXPECT_EQ
(
&
bar
,
m
);
}
else
{
}
else
{
ADD_FAILURE
()
<<
"Dynamic downcast returned null."
;
ADD_FAILURE
()
<<
"Dynamic downcast returned null."
;
}
}
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Baz
&
>
(
foo
)
==
nullptr
);
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Baz
>
(
foo
)
==
nullptr
);
#endif
#endif
}
}
...
...
c++/src/kj/common.h
View file @
9227a0f3
...
@@ -162,19 +162,10 @@ void inlineRequireFailure(
...
@@ -162,19 +162,10 @@ void inlineRequireFailure(
// =======================================================================================
// =======================================================================================
// Template metaprogramming helpers.
// Template metaprogramming helpers.
template
<
typename
T
>
template
<
typename
T
>
struct
NoInfer_
{
typedef
T
Type
;
};
struct
NoInfer_
{
template
<
typename
T
>
using
NoInfer
=
typename
NoInfer_
<
T
>::
Type
;
// Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
// Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
// the type based on the parameter value. There's something in the standard library for this but
// the type based on the parameter value.
// I didn't want to #include type_traits or whatever.
typedef
T
Type
;
};
template
<
typename
T
>
using
NoInfer
=
typename
NoInfer_
<
T
>::
Type
;
template
<
typename
T
>
struct
RemoveReference_
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
RemoveReference_
<
T
&>
{
typedef
T
Type
;
};
template
<
typename
T
>
using
RemoveReference
=
typename
RemoveReference_
<
T
>::
Type
;
template
<
typename
T
>
struct
RemoveConst_
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
RemoveConst_
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
RemoveConst_
<
const
T
>
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
RemoveConst_
<
const
T
>
{
typedef
T
Type
;
};
...
@@ -265,15 +256,7 @@ template <typename T, typename U> using EnableIfDifferent = typename EnableIfDif
...
@@ -265,15 +256,7 @@ template <typename T, typename U> using EnableIfDifferent = typename EnableIfDif
// when first encountered.
// when first encountered.
template
<
typename
T
>
constexpr
T
&&
mv
(
T
&
t
)
noexcept
{
return
static_cast
<
T
&&>
(
t
);
}
template
<
typename
T
>
constexpr
T
&&
mv
(
T
&
t
)
noexcept
{
return
static_cast
<
T
&&>
(
t
);
}
template
<
typename
T
>
constexpr
T
&&
fwd
(
NoInfer
<
T
>&
t
)
noexcept
{
return
static_cast
<
T
&&>
(
t
);
}
template
<
typename
T
>
constexpr
T
&&
fwd
(
RemoveReference
<
T
>&
t
)
noexcept
{
return
static_cast
<
T
&&>
(
t
);
}
template
<
typename
T
>
constexpr
T
&&
fwd
(
RemoveReference
<
T
>&&
t
)
noexcept
{
static_assert
(
!
isLvalueReference
<
T
>
(),
"Attempting to forward rvalue as lvalue reference."
);
return
static_cast
<
T
&&>
(
t
);
}
template
<
typename
T
,
typename
U
>
template
<
typename
T
,
typename
U
>
auto
min
(
T
&&
a
,
U
&&
b
)
->
decltype
(
a
<
b
?
a
:
b
)
{
return
a
<
b
?
a
:
b
;
}
auto
min
(
T
&&
a
,
U
&&
b
)
->
decltype
(
a
<
b
?
a
:
b
)
{
return
a
<
b
?
a
:
b
;
}
...
@@ -655,12 +638,12 @@ inline constexpr ArrayPtr<T> arrayPtr(T* begin, T* end) {
...
@@ -655,12 +638,12 @@ inline constexpr ArrayPtr<T> arrayPtr(T* begin, T* end) {
}
}
// =======================================================================================
// =======================================================================================
//
Upcast/downcast
//
Casts
template
<
typename
To
,
typename
From
>
template
<
typename
To
,
typename
From
>
To
upc
ast
(
From
&&
from
)
{
To
implicitC
ast
(
From
&&
from
)
{
// `
upcast<T>(value)` casts `value` to type `T` only if the conversion is implicit. Useful for
// `
implicitCast<T>(value)` casts `value` to type `T` only if the conversion is implicit. Useful
// e.g. resolving ambiguous overloads without sacrificing type-safety.
//
for
e.g. resolving ambiguous overloads without sacrificing type-safety.
return
kj
::
fwd
<
From
>
(
from
);
return
kj
::
fwd
<
From
>
(
from
);
}
}
...
@@ -675,39 +658,32 @@ Maybe<To&> dynamicDowncastIfAvailable(From& from) {
...
@@ -675,39 +658,32 @@ Maybe<To&> dynamicDowncastIfAvailable(From& from) {
// Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed
// Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed
// we should have a separate cast function like dynamicCrosscastIfAvailable().
// we should have a separate cast function like dynamicCrosscastIfAvailable().
if
(
false
)
{
if
(
false
)
{
kj
::
upcast
<
From
*>
(
upcast
<
RemoveReference
<
To
>
*>
(
nullptr
));
kj
::
implicitCast
<
From
*>
(
kj
::
implicitCast
<
To
*>
(
nullptr
));
}
}
#if KJ_NO_RTTI
#if KJ_NO_RTTI
return
nullptr
;
return
nullptr
;
#else
#else
return
dynamic_cast
<
RemoveReference
<
To
>
*>
(
&
from
);
return
dynamic_cast
<
To
*>
(
&
from
);
#endif
#endif
}
}
template
<
typename
To
,
typename
From
>
template
<
typename
To
,
typename
From
>
To
downcast
(
From
*
from
)
{
To
&
downcast
(
From
&
from
)
{
// Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a
// Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a
// static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify
// static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify
// that the value really has the requested type.
// that the value really has the requested type.
// Force a compile error if To is not a subtype of From.
// Force a compile error if To is not a subtype of From.
if
(
false
)
{
if
(
false
)
{
kj
::
upcast
<
From
*>
(
To
(
));
kj
::
implicitCast
<
From
*>
(
kj
::
implicitCast
<
To
*>
(
nullptr
));
}
}
#if !KJ_NO_RTTI
#if !KJ_NO_RTTI
KJ_IREQUIRE
(
from
==
nullptr
||
dynamic_cast
<
To
>
(
from
)
!=
nullptr
,
KJ_IREQUIRE
(
dynamic_cast
<
To
*>
(
&
from
)
!=
nullptr
,
"Value cannot be downcast() to requested type."
);
"Value cannot be downcast() to requested type."
);
#endif
#endif
return
static_cast
<
To
>
(
from
);
return
static_cast
<
To
&>
(
from
);
}
template
<
typename
To
,
typename
From
>
To
downcast
(
From
&
from
)
{
// Reference version of downcast().
return
*
kj
::
downcast
<
RemoveReference
<
To
>*>
(
&
from
);
}
}
}
// namespace kj
}
// namespace kj
...
...
c++/src/kj/memory.h
View file @
9227a0f3
...
@@ -55,7 +55,7 @@ public:
...
@@ -55,7 +55,7 @@ public:
// Helper wrapper around disposeImpl().
// Helper wrapper around disposeImpl().
//
//
// If T is polymorphic, calls `disposeImpl(dynamic_cast<void*>(object))`, otherwise calls
// If T is polymorphic, calls `disposeImpl(dynamic_cast<void*>(object))`, otherwise calls
// `disposeImpl(
upc
ast<void*>(object))`.
// `disposeImpl(
implicitC
ast<void*>(object))`.
//
//
// Callers must not call dispose() on the same pointer twice, even if the first call throws
// Callers must not call dispose() on the same pointer twice, even if the first call throws
// an exception.
// an exception.
...
...
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