3.0.0
Freundlich's C++ toolkit
Classes | Functions
fcppt.literal

Description

Literals or polymorphic integer constants.

Motivation

In C++, most literals are polymorphic in a sense that they can be implicitly converted to different types. For example, 0 can be used in places where nullptr can or to initialize a float to 0.f. Using literals like this, however, doesn't work to initialize integer-like types with explicit constructors or types that require special factory functions. This can quickly become a problem in generic code. Consider a generic function that tries to divide its argument by two.

template<
typename T
>
T
half(
T const _value
)
{
return
_value
/
2;
}

A lot of types provide an operator/ but they can't be implicitly converted from literals, for example strong typedefs.

int,
strong_int
);
void
try_strong()
{
// Doesn't work
/*half(
strong_int(
10
)
);*/
}

Specializing literals

The code above obviously doesn't work, so you might conclude from this example that we should change the function half to say T{2} instead of 2. However, other types like units without quantities in Boost.Units can only be initialized by a special factory function. Therefore, fcppt provides a customization point which is used to create objects from literals. For example, we could have found the following type inside a library:

namespace mine
{
class custom_type
{
public:
static
custom_type
int const _value
)
{
return
custom_type{
_value
};
}
int
get() const
{
return
value_;
}
private:
explicit
custom_type(
int const _value
)
:
value_{
_value
}
{
}
int value_;
};
inline
custom_type
custom_type const _left,
custom_type const _right
)
{
return
_left.get()
/
_right.get()
);
}
}

To make fcppt::literal work with this type, we need to provide a specialization for fcppt::make_literal.

namespace fcppt
{
template<>
struct make_literal<
mine::custom_type
>
{
typedef
mine::custom_type
decorated_type;
template<
typename Fundamental
>
static
mine::custom_type
get(
Fundamental const _value
)
{
static_assert(
std::is_same<
Fundamental,
int
>::value,
"custom_types should be initialized by integers"
);
return
_value
);
}
};
}

Using literals

In order to make the half function work, we call fcppt::literal.

template<
typename T
>
T
half_2(
T const _value
)
{
return
_value
/
T
>(
2
);
}

We can then call our half_2 function with custom_type

void
literal_use()
{
// Prints 2
<<
half_2(
4
)
).get()
<<
'\n';
}
Note
As a general rule of thumb, you should only use literals of type int with fcppt::literal but this isn't enforced by the type system because it might be too restrictive.

Classes

struct  fcppt::make_literal< Type, Enable >
 
struct  fcppt::strong_typedef< Type, Tag >>
 

Functions

template<typename Type , typename Arg >
constexpr fcppt::make_literal< Type >::decorated_type fcppt::literal (Arg const &&_integral)
 Creates a literal of a type. More...
 

Function Documentation

◆ literal()

template<typename Type , typename Arg >
constexpr fcppt::make_literal< Type>::decorated_type fcppt::literal ( Arg const &&  _integral)

Creates a literal of a type.

Creates a literal of type Type from the value _integral, using fcppt::make_literal to do any conversions if necessary.

Template Parameters
TypeThe literal type to create. Must be a value type. See fcppt::type_traits::is_value.
ArgAn arithmetic type.