https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122922
Bug ID: 122922
Summary: Valid code rejected because of interaction of friend
function and global module fragment
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: alberto.gcc.bugzilla at gmail dot com
Target Milestone: ---
Hello
The example bellow works with G++ 15 but is rejected with 16.
This is what I could reduce it to:
// Tensor.cpp
export module VF:Tensor;
import std;
export
namespace VF
{
template<std::size_t d, std::size_t r1>
struct TTensor
{
TTensor<d, r1 - 1u> TensorArr[d];
template<std::size_t... i>
std::istream &Read(std::index_sequence<i...>, std::istream &is)
{ return (is >> ... >> TensorArr[i]); }
friend std::istream &operator >>(std::istream &is, TTensor<d, r1> &Tensor)
{ return Tensor.Read(std::make_index_sequence<d>{}, is); }
};
template<std::size_t d>
struct TTensor<d, 0u>
{
double Escalar;
constexpr TTensor() = default;
constexpr TTensor(double const Escalar_) :
Escalar(Escalar_) {}
};
template<std::size_t d>
using TVector = TTensor<d, 1u>;
}
// Malla.cpp
module;
#include <vector>
#include <string>
export module VF:Malla;
import :Tensor;
import std;
namespace VF
{
export
template<std::size_t d>
class TCara
{
private:
std::vector<TVector<d> const *> const PtoPtrVec;
public:
TCara(std::vector<TVector<d> const *> &&PtoPtrVec_) :
PtoPtrVec(std::move(PtoPtrVec_)) {}
};
export
template<std::size_t d>
class TCelda
{
public:
enum ETipo { TRIAN };
private:
std::vector<TVector<d> const *> const PtoPtrVec;
private:
template<ETipo>
std::vector<TCara<d>> CaraVec_() const;
};
template<>
template<>
std::vector<TCara<2u>>
inline TCelda<2u>::CaraVec_<TCelda<2u>::TRIAN>() const
{
return {{{PtoPtrVec[0u], PtoPtrVec[2u]}},
{{PtoPtrVec[2u], PtoPtrVec[1u]}},
{{PtoPtrVec[1u], PtoPtrVec[0u]}}};
}
}
// Campo.cpp
export module VF:Campo;
import :Tensor;
import std;
export
namespace VF
{
template<std::size_t d, std::size_t r>
class TCampo
{
private:
std::unique_ptr<TTensor<d, r>[]> TensorPtr;
public:
TCampo(std::size_t N) :
TensorPtr(std::make_unique<TTensor<d, r>[]>(N)) {}
};
}
// VF.cpp
export module VF;
export import :Tensor;
export import :Malla;
export import :Campo;
// Cavity.cpp
import VF;
import std;
int main()
{
VF::TCampo<2, 1> U(1000);
return 0;
}
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only Tensor.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only Malla.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only Campo.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only VF.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules Cavity.cpp -o a.out
En el fichero incluido desde
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/memory:80,
desde
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/x86_64-pc-linux-gnu/bits/stdc++.h:56,
desde
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/bits/std.cc:26,
of module std, imported at Cavity.cpp:3:
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/bits/unique_ptr.h: In
instantiation of ‘constexpr std::__detail::__unique_ptr_array_t<_Tp>
std::make_unique(size_t) [con _Tp = VF::TTensor@VF<2, 1> [];
__detail::__unique_ptr_array_t<_Tp> =
__detail::__unique_ptr_array_t<VF::TTensor@VF<2, 1> []>; size_t = long unsigned
int]’:
required from ‘VF::TCampo@VF<d, r>::TCampo(std::size_t) [con long unsigned int
d = 2; long unsigned int r = 1; std::size_t = long unsigned int]’
Campo.cpp:19:48:
19 | TensorPtr(std::make_unique<TTensor<d, r>[]>(N)) {}
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
required from here
Cavity.cpp:7:24:
7 | VF::TCampo<2, 1> U(1000);
| ^
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/bits/unique_ptr.h:1101:30:
error: inicialización por valor del tipo de dato incompleto ‘VF::TTensor@VF<2,
0> [2]’
1101 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../gcc-16/gcc-16/bin/g++ -v
Usando especificaciones internas.
COLLECT_GCC=../gcc-16/gcc-16/bin/g++
COLLECT_LTO_WRAPPER=/home/alberto/gcc-16/gcc-16/libexec/gcc/x86_64-pc-linux-gnu/16.0.0/lto-wrapper
Objetivo: x86_64-pc-linux-gnu
Configurado con: ../gcc/configure --enable-languages=c++ --disable-multilib
--disable-bootstrap --prefix=/home/alberto/gcc-16/gcc-16/
Modelo de hilos: posix
Algoritmos de compresión LTO admitidos: zlib zstd
gcc versión 16.0.0 20251129 (experimental) (GCC)