I am getting a warning (turned into an error with -Werror) about missing-field-initializers when using designated initializers for the fields in my struct, because I'm not initializing fields in a 3rd party base class, boost::intrusive::unordered_set_base_hook
error: missing initializer for member ‘foo::boost::intrusive::unordered_set_base_hook<>’
[-Werror=missing-field-initializers]
10 | foo f { .bar = 1 };
| ^
Here is a minimal reproducible example:
#include <boost/intrusive/unordered_set.hpp>
struct foo : boost::intrusive::unordered_set_base_hook<>
{
int bar;
};
int main()
{
foo f { .bar = 1 };
return 0;
}
Here is my CMakeLists.txt file. I am specifying that the boost include dir is a SYSTEM directory, to suppress warnings from boost headers.
cmake_minimum_required(VERSION 3.18)
project(scratch_test)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Boost)
add_executable(scratch
main.cpp
)
target_compile_options(scratch
PRIVATE
-Wmissing-field-initializers
-Werror
)
target_include_directories(scratch
SYSTEM PRIVATE
${Boost_INCLUDE_DIRS}
)
Looking at the source code for boost::intrusive, in effect the code effectively looks like this:
struct generic_hook
{
void* next_;
};
struct unordered_set_base_hook : generic_hook
{
};
So indeed next_ is not initialized.
I even tried to modify my code to use my own base class, which I in-class initialize to nullptr:
struct generic_hook
{
void* next_ {nullptr};
};
struct unordered_set_base_hook : generic_hook
{
};
struct foo : unordered_set_base_hook
{
int bar;
};
int main()
{
foo f { .bar = 1 };
return 0;
}
I still get the error:
error: missing initializer for member ‘foo::unordered_set_base_hook’
[-Werror=missing-field-initializers]
17 | foo f { .bar = 1 };
| ^
Is this a legitimate warning/error?
I do not really want to be responsible for initializing 3rd party dependency base class members; what is the correct course of action here?
The error is not about void* next_ being uninitialized, but about you not providing an explicit initializer for something in your class. This warning is meant to warn you if you accidentally forget that a base class or data member exists when initializing, most useful for cases like:
struct Foo {
int x;
int y;
int z;
};
Foo f{ .x = 1, .z = 2 }; // Forgot to provide an initializer for y, should write .y = 0 or .y = {}.
There's currently no way to use designated intializers with base classes, so you would have to write:
int main()
{
foo f { boost::intrusive::unordered_set_base_hook<>(), 1 };
// Or
foo f { {}, 1 };
return 0;
}
Aggregate initialization is kind of a pain in general if there are base classes, I would recommend just writing a constructor if you want to keep the error. Or use -Wno-error=missing-field-initializers to downgrade to a warning or -Wno-missing-field-initializers to silence completely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With