C++ 错误模块片段和命名空间?

发布于 2025-01-12 12:17:04 字数 2608 浏览 5 评论 0原文

我想构建一个带有多个实现文件的单个模块。一个包含结构的文件由两个实现文件使用。

当我编译时,我在 gcc trunk (12) 和 11 中收到以下错误:

$HOME/bin/bin/g++ -std=c++20 -fmodules-ts -g -o test_optimization test_optimization.cpp optimization.cpp opt_structs.cpp golden.cpp brent.cpp
test_optimization.cpp: In function ‘int main()’:
test_optimization.cpp:13:3: error: ‘emsr’ has not been declared
   13 |   emsr::MinBracket<double> mb;
      |   ^~~~
test_optimization.cpp:13:20: error: expected primary-expression before ‘double’
   13 |   emsr::MinBracket<double> mb;
      |                    ^~~~~~

从我根本不理解模块到不完整的 g++ 实现等等,可能会发生一些非排他性的事情......

Main测试器(test_optimization.cpp):

#include <cmath>

import emsr.opt;

int
main()
{
  emsr::MinBracket<double> mb;
}

模块接口(optimization.cpp):

export module emsr.opt;
export import :golden;
export import :brent;

一个实现模块(golden.cpp):

module;

#include <cmath>
#include <numbers>

export module emsr.opt:golden;

export import :structs;

namespace emsr
{
  template<typename Func, typename Real>
    void
    mean_bracket(Func func, MinBracket<Real>& mb)
    { }

  template<typename Func, typename Real>
    FuncPt<Real>
    golden(Func func, MinBracket<Real>& mb, Real tol)
    { return FuncPt<Real>(); }
} // namespace emsr

另一个实现模块(brent.cpp):

module;

#include <cmath>
#include <numbers>

export module emsr.opt:brent;

export import :structs;

namespace emsr
{
  template<typename Func, typename Real>
    FuncPt<Real>
    brent(Func func, Real ax, Real bx, Real cx, Real tol)
    { return FuncPt<Real>(); }

  template<typename Func, typename Deriv, typename Real>
    FuncPt<Real>
    brent_deriv(Func func, Deriv deriv, Real ax, Real bx, Real cx, Real tol)
    { return FuncPt<Real>(); }
} // namespace emsr

结构模块片段(opt_structs.cpp):

export module emsr.opt:structs;

namespace emsr
{
  template<typename Real>
    struct FuncPt
    {
      Real arg;
      Real val;

      FuncPt() = default;
    };

  template<typename Real>
    struct MinBracket
    {
      FuncPt<Real> a;
      FuncPt<Real> b;
      FuncPt<Real> c;
    };

  template<typename Real>
    struct DerivPt
    {
      Real arg;
      Real val;
      Real der;

      DerivPt() = default;
    };
}

I want to build a single module with several implementation files. One file with structs is used by two implementation files.

When I compile I get the following error in gcc trunk (12) and also 11:

$HOME/bin/bin/g++ -std=c++20 -fmodules-ts -g -o test_optimization test_optimization.cpp optimization.cpp opt_structs.cpp golden.cpp brent.cpp
test_optimization.cpp: In function ‘int main()’:
test_optimization.cpp:13:3: error: ‘emsr’ has not been declared
   13 |   emsr::MinBracket<double> mb;
      |   ^~~~
test_optimization.cpp:13:20: error: expected primary-expression before ‘double’
   13 |   emsr::MinBracket<double> mb;
      |                    ^~~~~~

There could be several non-exclusive things going on from my not understanding modules at all to incomplete g++ implementation and on and on...

Main tester (test_optimization.cpp):

#include <cmath>

import emsr.opt;

int
main()
{
  emsr::MinBracket<double> mb;
}

Module interface (optimization.cpp):

export module emsr.opt;
export import :golden;
export import :brent;

One implementation module (golden.cpp):

module;

#include <cmath>
#include <numbers>

export module emsr.opt:golden;

export import :structs;

namespace emsr
{
  template<typename Func, typename Real>
    void
    mean_bracket(Func func, MinBracket<Real>& mb)
    { }

  template<typename Func, typename Real>
    FuncPt<Real>
    golden(Func func, MinBracket<Real>& mb, Real tol)
    { return FuncPt<Real>(); }
} // namespace emsr

Another implementation module (brent.cpp):

module;

#include <cmath>
#include <numbers>

export module emsr.opt:brent;

export import :structs;

namespace emsr
{
  template<typename Func, typename Real>
    FuncPt<Real>
    brent(Func func, Real ax, Real bx, Real cx, Real tol)
    { return FuncPt<Real>(); }

  template<typename Func, typename Deriv, typename Real>
    FuncPt<Real>
    brent_deriv(Func func, Deriv deriv, Real ax, Real bx, Real cx, Real tol)
    { return FuncPt<Real>(); }
} // namespace emsr

Structs module fragment (opt_structs.cpp):

export module emsr.opt:structs;

namespace emsr
{
  template<typename Real>
    struct FuncPt
    {
      Real arg;
      Real val;

      FuncPt() = default;
    };

  template<typename Real>
    struct MinBracket
    {
      FuncPt<Real> a;
      FuncPt<Real> b;
      FuncPt<Real> c;
    };

  template<typename Real>
    struct DerivPt
    {
      Real arg;
      Real val;
      Real der;

      DerivPt() = default;
    };
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花开浅夏 2025-01-19 12:17:04

我也在尝试用 gcc 找出模块,我无法发表评论,所以我会在这里发布。

gcc 文档 说:

标准库标头单元:

<块引用>

标准库不作为可导入的标头单元提供。如果要导入此类单元,则必须首先显式构建它们。如果您不小心执行此操作,则可能有多个声明,模块机制必须合并这些声明 - 编译器资源使用情况可能会受到您将头文件划分为头单元的方式的影响。

<块引用>

不需要也不支持新的源文件后缀。如果您希望使用非标准后缀(请参阅总体选项),您还需要提供 -x c++ 选项。2


根据 这篇博文,使用 gcc,您需要根据我的理解单独编译标头。他们使用标准库中的 iostream 作为示例。

虽然 Clang 附带了标准标头到模块的映射。使用GCC,我们需要手动编译iostream。

> g++ -std=c++20 -fmodules-ts -xc++-system-header iostream
> g++ -std=c++20 -fmodules-ts hello_modular_world.cc

看起来他们也使用 import

; 语法而不是 include。

> cat hello_modular_world.cc
import <iostream>;
int main() {
    std::cout << "Hello Modular World!\n";
}

我不确定这是否可以接受,但它有效,这就是我所做的:

我编译了系统标头:

> g++-12 -std=c++20 -fmodules-ts -xc++-system-header cmath
> g++-12 -std=c++20 -fmodules-ts -xc++-system-header numbers

我更改了这样的代码:

opt_structs.cpp

export module emsr.opt:structs;

export namespace emsr {
template <typename Real> struct FuncPt {
  Real arg;
  Real val;

  FuncPt() = default;
};

template <typename Real> struct MinBracket {
  FuncPt<Real> a;
  FuncPt<Real> b;
  FuncPt<Real> c;
};

template <typename Real> struct DerivPt {
  Real arg;
  Real val;
  Real der;

  DerivPt() = default;
};
} // namespace emsr

gold.cpp

module;

import <cmath>;
import <numbers>;

export module emsr.opt:golden;

export import :structs;

export namespace emsr {
template <typename Func, typename Real>
void mean_bracket(Func func, MinBracket<Real> &mb) {}

template <typename Func, typename Real>
FuncPt<Real> golden(Func func, MinBracket<Real> &mb, Real tol) {
  return FuncPt<Real>();
}
} // namespace emsr

brent.cpp

module;

import <cmath>;
import <numbers>;

export module emsr.opt:brent;

export import :structs;

export namespace emsr {
template <typename Func, typename Real>
FuncPt<Real> brent(Func func, Real ax, Real bx, Real cx, Real tol) {
  return FuncPt<Real>();
}

template <typename Func, typename Deriv, typename Real>
FuncPt<Real> brent_deriv(Func func, Deriv deriv, Real ax, Real bx, Real cx,
                         Real tol) {
  return FuncPt<Real>();
}
} // namespace emsr

optimization.cpp(相同)

export module emsr.opt;
export import :golden;
export import :brent;

test_optimization。 我所做的只是

import <cmath>;
import emsr.opt;

int main() {
  emsr::MinBracket<double> mb;
  return 0;
}

#include 更改为 import

; 并导出命名空间 emsr

然后我像这样编译:

> g++-12 -std=c++20 -fmodules-ts -g -c opt_structs.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c brent.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c golden.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c optimization.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c test_optimization.cpp
> g++-12 -std=c++20 test_optimization.o opt_structs.o brent.o golden.o optimization.o -o test_optimization

> ./test_optimization

请注意,我必须先编译 opt_structs.cpp,然后编译 golden.cppbrent.cpp,然后 optimization.cpp 然后是 main 文件。

再说一次,我不知道这是否是最好的或正确的方法,我仍在学习,但这就是我试图解决这个问题的方法。

I'm trying to figure out modules with gcc as well, I can't comment so I'll post here.

The gcc documentation says:

Standard Library Header Units:

The Standard Library is not provided as importable header units. If you want to import such units, you must explicitly build them first. If you do not do this with care, you may have multiple declarations, which the module machinery must merge—compiler resource usage can be affected by how you partition header files into header units.

No new source file suffixes are required or supported. If you wish to use a non-standard suffix (see Overall Options), you also need to provide a -x c++ option too.2

According to this blog post, with gcc you need to compile headers separately from what I understand. They use iostream from the standard library as an example.

While Clang comes with a mapping of standard headers to modules. Using GCC, we need to compile iostream manually.

> g++ -std=c++20 -fmodules-ts -xc++-system-header iostream
> g++ -std=c++20 -fmodules-ts hello_modular_world.cc

It also looks like they use import <header>; syntax instead of include.

> cat hello_modular_world.cc
import <iostream>;
int main() {
    std::cout << "Hello Modular World!\n";
}

I'm not sure if this is acceptable but it works, this is what I did:

I compiled the system headers:

> g++-12 -std=c++20 -fmodules-ts -xc++-system-header cmath
> g++-12 -std=c++20 -fmodules-ts -xc++-system-header numbers

I changed the code like this:

opt_structs.cpp

export module emsr.opt:structs;

export namespace emsr {
template <typename Real> struct FuncPt {
  Real arg;
  Real val;

  FuncPt() = default;
};

template <typename Real> struct MinBracket {
  FuncPt<Real> a;
  FuncPt<Real> b;
  FuncPt<Real> c;
};

template <typename Real> struct DerivPt {
  Real arg;
  Real val;
  Real der;

  DerivPt() = default;
};
} // namespace emsr

golden.cpp

module;

import <cmath>;
import <numbers>;

export module emsr.opt:golden;

export import :structs;

export namespace emsr {
template <typename Func, typename Real>
void mean_bracket(Func func, MinBracket<Real> &mb) {}

template <typename Func, typename Real>
FuncPt<Real> golden(Func func, MinBracket<Real> &mb, Real tol) {
  return FuncPt<Real>();
}
} // namespace emsr

brent.cpp

module;

import <cmath>;
import <numbers>;

export module emsr.opt:brent;

export import :structs;

export namespace emsr {
template <typename Func, typename Real>
FuncPt<Real> brent(Func func, Real ax, Real bx, Real cx, Real tol) {
  return FuncPt<Real>();
}

template <typename Func, typename Deriv, typename Real>
FuncPt<Real> brent_deriv(Func func, Deriv deriv, Real ax, Real bx, Real cx,
                         Real tol) {
  return FuncPt<Real>();
}
} // namespace emsr

optimization.cpp (the same)

export module emsr.opt;
export import :golden;
export import :brent;

test_optimization.cpp

import <cmath>;
import emsr.opt;

int main() {
  emsr::MinBracket<double> mb;
  return 0;
}

All I did was change #includes to import <header>; and exported the namespace emsr.

Then I compiled like this:

> g++-12 -std=c++20 -fmodules-ts -g -c opt_structs.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c brent.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c golden.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c optimization.cpp
> g++-12 -std=c++20 -fmodules-ts -g -c test_optimization.cpp
> g++-12 -std=c++20 test_optimization.o opt_structs.o brent.o golden.o optimization.o -o test_optimization

> ./test_optimization

Note that I had to compile opt_structs.cpp first, then golden.cpp and brent.cpp, then optimization.cpp and then the main file.

Again, I don't know if this is the best or right way, I'm still learning, but this is what I did trying to figure this out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文