当我尝试使用 std::format() 链接某些内容时,为什么会出现链接器错误?

问题描述 投票:0回答:1

我使用的是 Marc Gregoire 所著的《Professional C++,第五版》第 1 章中的示例,并添加了一些修改,以便 VSCode 中的 Intellisense 不会出现错误:

员工模块.cppm:

export module employee;

export struct Employee {
  char firstInitial;
  char lastInitial;
  int employeeNumber;
  int salary;
};

员工.cpp:

#ifdef __INTELLISENSE__
#include <iostream>
#include <format>
#include "employee-module.cppm"
#else
import <iostream>;
import <format>;
import employee;
#endif

using namespace std;

int main() {
  Employee anEmployee;
  anEmployee.firstInitial = 'J';
  anEmployee.lastInitial = 'D';
  anEmployee.employeeNumber = 42;
  anEmployee.salary = 80'000;

  cout << format("Employee: {}{}", anEmployee.firstInitial,
                 anEmployee.lastInitial)
       << endl;
  cout << format("Number: {}", anEmployee.employeeNumber) << endl;
  cout << format("Salary: ${}", anEmployee.salary) << endl;
}

这是我的 Makefile,以防我遗漏了什么:

CXX_VERSION = 23

CXX = g++
CXXFLAGS = -std=c++$(CXX_VERSION) -fmodules-ts
EXE = employee hello
SYSTEM_MODULES =    fstream filesystem thread algorithm any array atomic barrier bit bitset charconv chrono compare complex concepts condition_variable coroutine deque \
                    exception expected format forward_list functional future initializer_list istream iomanip ios iosfwd iostream iterator latch limits list locale map \
                    memory memory_resource mutex new numbers numeric optional ostream queue ranges ratio regex scoped_allocator semaphore set shared_mutex \
                    source_location span sstream stack stacktrace stdexcept stdfloat stop_token streambuf string string_view syncstream system_error tuple type_traits \
                    typeindex typeinfo unordered_map unordered_set utility valarray variant vector version execution random spanstream
.PHONY = all clean system-modules

default: all

all: $(EXE)

employee: employee-module.o employee.o
    $(CXX) $(CXXFLAGS) -o $@ $^

hello: hello.o
    $(CXX) $(CXXFLAGS) -o $@ $^

%.o: %.cpp
    $(CXX) $(CXXFLAGS) -c $^

%.o: %.cppm
    $(CXX) $(CXXFLAGS) -c -x c++ $^

clean:
    rm -f $(EXE) *.o

deepclean: clean
    rm -rf gcm.cache/

$(SYSTEM_MODULES):
    $(CXX) $(CXXFLAGS) -x c++-system-header $@

system-modules: $(SYSTEM_MODULES) | gcm.cache/

构建它会给出以下输出,当它尝试链接最终的可执行文件时,会因链接器错误而终止:

$ make
g++ -std=c++23 -fmodules-ts -c -x c++ employee-module.cppm
g++ -std=c++23 -fmodules-ts -c employee.cpp
g++ -std=c++23 -fmodules-ts -o employee employee-module.o employee.o
/usr/bin/ld: employee.o: in function `unsigned char std::__detail::__from_chars_alnum_to_val<false>(unsigned char)':
employee.cpp:(.text._ZNSt8__detail25__from_chars_alnum_to_valILb0EEEhh[_ZNSt8__detail25__from_chars_alnum_to_valILb0EEEhh]+0x12): undefined reference to `std::__detail::__from_chars_alnum_to_val_table<false>::value'
collect2: error: ld returned 1 exit status
make: *** [Makefile:18: employee] Error 1

系统模块均按预期构建并处于

gcm.cache/
状态(如果不是,我会收到编译器错误)。

我的第一个想法是 libstdc++ 没有被链接进来,所以凭直觉我在构建和链接步骤的命令行中添加了

-lstdc++
,但我得到了相同的结果。

此外,我重写了程序,只使用

cout
并将变量直接放入流中,完全避免使用
format()
。它完全按照预期构建、链接和运行,没有错误,即使我将
-lstdc++
排除在命令行之外也是如此。

郑重声明,Makefile 中的

"hello"
目标可以正常构建、链接和运行,这是一个使用
"Hello, World!"
的简单的
<iostream>
程序。

所以,然后我用谷歌搜索了(未损坏的)符号名称,希望这能提供一些见解。据我所知,

std::detail::from_chars_alnum_to_val
charconv
模块的一部分,所以我构建了它,将
import <charconv>;
添加到
employee.cpp
,然后再次尝试。编译得很好,但同样的链接器错误。

接下来,我决定疯狂地构建每个标准库模块(因此是长得可笑的

SYSTEM_HEADERS
变量)。没有骰子,同样的链接器错误。

我缺少一些基本的东西吗?

我使用的是 Slackware Linux 当前版本、64 位 Intel、g++ 13.2.0、binutils 2.41

c++ makefile g++ c++23
1个回答
0
投票

您可以尝试升级

gcc
来解决此问题。

我尝试了

gcc 13.3.0
,但错误仍然存在。

但是当您将

gcc
升级到
14.1.0
时,一切正常。

sudo update-alternatives --config gcc

  0            /usr/bin/gcc-12           220       auto mode
  1            /opt/gcc-13.3.0/bin/gcc   133       manual mode
* 2            /opt/gcc-14.1.0/bin/gcc   141       manual mode
  3            /usr/bin/gcc-12           220       manual mode

g++ -std=c++20 -fmodules-ts -o employee employee-module.o employee.o

我想

gcc
C++20
模块的支持仍在进行中。

© www.soinside.com 2019 - 2024. All rights reserved.