My generated code always used unnecessary many parenthesis simply to make certain, that the C code was actually doing what the AST expressed. This is first time I'm getting this compiler error, which I cannot explain -- also before I've used custom types.
(define G_ERROR to get an error...) Visual C 2019 yields the following error:
cl -c tmp0.cpp -I ..\Documents\WORK\boost_1_77_0 -DG_ERROR
tmp0.cpp(32): error C2066: cast to function type is illegal
tmp0.cpp(40): error C2675: unary ' ': 'abstractValue<32>' does not define this operator or a conversion to a type acceptable to the predefined operator
tmp0.cpp(40): error C2088: ' ': illegal for class
g v10 yields the following error:
g -10 -std=c 11 -c tmp0.cpp -I /mnt/c/Users/userName/Documents/WORK/boost_1_77_0/ -DG_ERROR
tmp0.cpp:40:3: error: no match for ‘operator ’ (operand type is ‘abstractValue<>’)
#include <vector>
#include <boost/optional.hpp>
#include <type_traits>
#include <functional>
#include <initializer_list>
#include <set>
struct undetermined
{
};
template<std::size_t SIZE=32>
class abstractValue
{ public:
abstractValue(const double);
abstractValue(const undetermined&);
abstractValue operator (const abstractValue&) const;
};
struct instance
{
double DTEMP;
abstractValue<> function_231(
std::vector<boost::optional<abstractValue<>> >&_r
) const{
auto &r = _r.at(231);
if (
!r
)r =
#ifdef G_ERROR
(
#endif
abstractValue<>(
undetermined()
)
#ifdef G_ERROR
)
#endif
(
abstractValue<>(
DTEMP
)
);
return r.value();
}
};
CodePudding user response:
abstractValue<>(undetermined())
Because both abstractValue<>
and undetermined
are types, there are two interpretations of this without further context:
It is a functional-style explicit cast expression creating a prvalue of type
abstractValue<>
with(undetermined())
its initializer.It is a type-id, namely the type of a function returning
abstract<>
with a single parameter of type "function without parameters returningundetermined
" (which is adjusted to "pointer to function without parameters returningundetermined
").
You want it to mean the first, not the second. When writing
abstractValue<>(undetermined()) /*...*/
it cannot have the meaning of 2. and
can only be the binary
operator, but because there are C-style explicit cast expressions in the form of (T)E
where T
is a type and E
an expression, in
(abstractValue<>(undetermined())) /*...*/
the whole expression could also be such a C-style explicit cast expression with abstractValue<>(undetermined())
being T
and /*...*/
being E
with
the unary
.
Because the grammar is ambiguous here, there is a rule saying that any construct that could be interpreted as a type-id in such a situation, is interpreted as a type-id. Therefore the interpretation as 2. is chosen here.
You can avoid this by either simply not using the extra parentheses (as seen they can not always be added without affecting the meaning of an expression) or you can use brace-initialization instead of initialization with parentheses, because braces cannot appear in a function type, disqualifying the 2. immediately in all contexts:
abstractValue<>{undetermined()}
or
abstractValue<>(undetermined{})
or
abstractValue<>{undetermined{}}