Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Handling incomplete type for automated formal in-argument type

10 views
Skip to first unread message

Alf P. Steinbach

unread,
Jan 8, 2016, 10:59:45 PM1/8/16
to
I just coded up the following to automate selection of a type for a
formal in-argument:

namespace impl {
template< class Type >
constexpr auto is_large_or_incomplete()
-> bool
{
return (sizeof_<Type>() == 0
? true
: sizeof_<Type>() > sizeof( Ptr_<void> )
);
}
} // namespace impl

template< class Arg >
using In_ = If_<
Any_of_<
Is_true_<impl::is_large_or_incomplete<Arg>()>,
Is_raw_array_<Arg>
>,
Then_<Ref_<const Arg>>,
Else_<const Arg>
>;

where “sizeof_” is a constexpr function that yields 0 for an incomplete
type.

Then when I started using this in the existing other code, it hit me that

• In a function declaration within class Foo, “In_<Foo>” will translate
to “Foo const&”, because here Foo is still incomplete.

• But in a function definition after the Foo class definition,
“In_<Foo>” can translate to just “Foo const”, because here Foo is complete.

So I'm not at all sure that the above is a good design. Should, instead,
e.g. incomplete argument type just not compile with automated selection
of the specific form? Or, maybe the whole idea of writing

void f( In_<Foo> x )

instead of e.g. (for array or large type)

void f( Foo const& x )

is ungood?


Cheers,

- Alf

Alf P. Steinbach

unread,
Jan 8, 2016, 11:09:06 PM1/8/16
to
On 1/8/2016 1:00 PM, Alf P. Steinbach wrote:
>
> Then when I started using this in the existing other code, it hit me that
>
> • In a function declaration within class Foo, “In_<Foo>” will translate
> to “Foo const&”, because here Foo is still incomplete.
>
> • But in a function definition after the Foo class definition,
> “In_<Foo>” can translate to just “Foo const”, because here Foo is complete.
>
> So I'm not at all sure that the above is a good design.

Well, I landed on a compromize: always translating “In_<T>” to reference
when “T” is a class type (and also when “T” is a raw array type). That
avoids any problems with incomplete type within a class definition. When
the small object should be passed by value, that can always be specified
explicitly as e.g. “In_value_<T>”:

<code>

//---------------------------------------------------------------------------
// Formal argument types:

// Works with template argument deduction, but is just a clarity
notation
// (descriptive, and removes from sight a visually distracting
`const`).
template< class Arg >
using In_ref_ = Ref_<const Arg>; // ← In_ref_

// Works with template argument deduction, but is just a clarity
notation
// (descriptive, and removes from sight a visually distracting
`const`).
template< class Arg
, class Enabled_ = If_<Not_<Is_raw_array_<Arg>>>
>
using In_value_ = const Arg; // ← In_value_

// Automated argument type selection.
// Note: can't work with template argument deduction; stricly for
known types.
template< class Arg >
using In_ = If_< // ← In_
Any_of_< std::is_class<Arg>, Is_raw_array_<Arg> >,
Then_<Ref_<const Arg>>,
Else_<const Arg>
>;

// Works with template argument deduction.
template< class Arg
, class Enabled_ = If_<Not_<std::is_const<Arg>>>
>
using In_out_ = Ref_<Arg>; // ← In_out_
</code>

The visual effect on function declarations can be seen in the latest
check-in of the cppx code, at <url:
https://github.com/alf-p-steinbach/cppx/commit/a5a185e781bc1b06971c4fc869dbefe2e0ea687c>.

Cheers!,

- Alf

0 new messages