boostorg / pfr

std::tuple like methods for user defined types without any macro or boilerplate code
https://boost.org/libs/pfr
Boost Software License 1.0
1.34k stars 161 forks source link

error: variable 'boost::pfr::detail::fake_object<Test>' is used but not defined #144

Closed linuxnyasha closed 12 months ago

linuxnyasha commented 1 year ago

In file included from error.cpp:1: In file included from /usr/include/boost/pfr.hpp:14: In file included from /usr/include/boost/pfr/core_name.hpp:17: In file included from /usr/include/boost/pfr/detail/core_name.hpp:23: In file included from /usr/include/boost/pfr/detail/core_name20_static.hpp:21: /usr/include/boost/pfr/detail/fake_object.hpp:20:16: error: variable 'boost::pfr::detail::fake_object' is used but not defined in this translation unit, and cannot be defined in any other translation unit because its type does not have linkage 20 | extern const T fake_object; | ^ error.cpp:7:29: note: used here 7 | (void)boost::pfr::detail::fake_object; | ^

#include <boost/pfr.hpp>

int main() {
  struct Test {
    int data;
  };
  (void)boost::pfr::detail::fake_object<Test>;
};
schaumb commented 1 year ago

fake_object is intentionally designed to be devoid of linkage, signifying its exclusive purpose for member name retrieval. It serves as a companion to declval<T>() by providing a compile-time "memory address" without actual utilization.

This behavior is not a defect, as long as the object remains encapsulated within the detail namespace. However, it becomes a bug if the error can be replicated without explicitly using fake_object.

linuxnyasha commented 1 year ago
#include <boost/pfr.hpp>
int main() {
  struct Test {
    int field;
  };
  static_assert(boost::pfr::get_name<0, Test>() == "field");
};
schaumb commented 1 year ago

Could you please provide details about the operating system, compiler (including version), and toolchain you are using? I am facing challenges in replicating the issue, and automated tests are yielding positive results. It's possible that the issue may be specific to your environment.

linuxnyasha commented 1 year ago

Gentoo Linux

clang --version
clang version 17.0.4
Target: x86_64-gentoo-linux-musl
Thread model: posix
InstalledDir: /usr/lib/llvm/17/bin
Configuration file: /etc/clang/x86_64-gentoo-linux-musl-clang.cfg
linuxnyasha commented 1 year ago

Can you show me a test that worked successfully? I didn't find one. Error on g++-13 (Gentoo 13.2.1_p20231014 p10) 13.2.1 20231014:

In file included from /usr/include/boost/pfr/detail/core_name20_static.hpp:21,
                 from /usr/include/boost/pfr/detail/core_name.hpp:23,
                 from /usr/include/boost/pfr/core_name.hpp:17,
                 from /usr/include/boost/pfr.hpp:14,
                 from lu.cpp:1:
/usr/include/boost/pfr/detail/fake_object.hpp:20:16: error: ‘const main()::Test boost::pfr::detail::fake_object<main()::Test>’, declared using local type ‘const main()::Test’, is used but never
defined [-fpermissive]
   20 | extern const T fake_object;
schaumb commented 1 year ago

The limitation says that

The Boost.PFRs extraction of field name has some limitations that depend on a C++ Standard and compiler capabilities: T should be usable like extern T t;, i.e. has a non-internal linkage.

Function local classes has no external linkage, so it will not work with those structures.


The tests can be found here, and the tests are run in GitHub actions, like here

schaumb commented 1 year ago

Hi @denzor200 ,

Is it possible to rename the fake_object or create a pre-checker object with a more meaningful name, such as passed_type_has_no_external_linkage with some comment? This would enhance the clarity of error messages.

denzor200 commented 1 year ago

Hi, @schaumb ,

Sure, PR will be created in the future

denzor200 commented 12 months ago

Here is the PR: https://github.com/boostorg/pfr/pull/146