Skip to content

Const generics: Constants using const generic structs don't quite work. #767

@emilio

Description

@emilio

cc @jorendorff (not sure of a great fix for this, for the record, filing so that I don't lose track of it).

I wanted to do something like this today:

#[repr(C)]
pub struct FixedPoint<const FRACTION_BITS: u16> {
    value: u16,
}

pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6;

#[repr(C)]
pub struct FontWeight(FixedPoint<FONT_WEIGHT_FRACTION_BITS>);

impl FontWeight {
    pub const NORMAL: FontWeight = FontWeight(FixedPoint { value: 400 << FONT_WEIGHT_FRACTION_BITS });
}

#[no_mangle]
pub extern "C" fn root(w: FontWeight) {}

That generates:

#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

constexpr static const uint16_t FONT_WEIGHT_FRACTION_BITS = 6;

template<uint16_t FRACTION_BITS>
struct FixedPoint {
  uint16_t value;
};

struct FontWeight {
  FixedPoint<FONT_WEIGHT_FRACTION_BITS> _0;
};
constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FixedPoint{ /* .value = */ (400 << FONT_WEIGHT_FRACTION_BITS) } };

extern "C" {

void root(FontWeight w);

} // extern "C"

Which looks like it could compile, but doesn't:

out.cpp:17:79: error: use of class template 'FixedPoint' requires template arguments
constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FixedPoint{ /* .value = */ (400 << FONT_WEIGHT_FRACTION_BITS) } };
                                                                              ^
out.cpp:10:8: note: template is declared here
struct FixedPoint {
       ^
1 error generated.

A workaround could be adding a type alias:

#[repr(C)]
pub struct FixedPoint<const FRACTION_BITS: u16> {
    value: u16,
}

pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6;

pub type FontWeightFixedPoint = FixedPoint<FONT_WEIGHT_FRACTION_BITS>;

#[repr(C)]
pub struct FontWeight(FontWeightFixedPoint);

impl FontWeight {
    pub const NORMAL: FontWeight = FontWeight(FontWeightFixedPoint { value: 400 << FONT_WEIGHT_FRACTION_BITS });
}

#[no_mangle]
pub extern "C" fn root(w: FontWeight) {}

But that doesn't quite cut it either because it doesn't generate the inner expression:

constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FontWeightFixedPoint{  } };

I think that should be fixable tho.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions