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