Visual Studio 为什么这个模板结构(专门化)在VS 2022中无法编译?

nnt7mjpx  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(177)

这段代码不会用MSVC编译,它包含C++ 20 spirit中的模板专门化。有人能帮忙吗?代码包含模板专门化,并使用模块,但它将无法工作。

  1. //Grid.cppm
  2. export module grid;
  3. export import :main;
  4. export import :string;
  1. //GridMain.cppm
  2. module;
  3. #include <cstddef>
  4. export module grid:main;
  5. import <stdexcept>;
  6. import <vector>;
  7. import <optional>;
  8. import <utility>;
  9. import <format>;
  10. export
  11. template <typename T>
  12. class Grid
  13. {
  14. public:
  15. explicit Grid(size_t width = DefaultWidth, size_t height = DefaultHeight);
  16. virtual ~Grid() = default;
  17. // Explicitly default a copy constructor and copy assignment operator.
  18. Grid(const Grid& src) = default;
  19. Grid& operator=(const Grid& rhs) = default;
  20. // Explicitly default a move constructor and move assignment operator.
  21. Grid(Grid&& src) = default;
  22. Grid& operator=(Grid&& rhs) = default;
  23. std::optional<T>& at(size_t x, size_t y);
  24. const std::optional<T>& at(size_t x, size_t y) const;
  25. size_t getHeight() const { return m_height; }
  26. size_t getWidth() const { return m_width; }
  27. static const size_t DefaultWidth{ 10 };
  28. static const size_t DefaultHeight{ 10 };
  29. private:
  30. void verifyCoordinate(size_t x, size_t y) const;
  31. std::vector<std::vector<std::optional<T>>> m_cells;
  32. size_t m_width{ 0 }, m_height{ 0 };
  33. };
  34. template <typename T>
  35. Grid<T>::Grid(size_t width, size_t height)
  36. : m_width{ width }
  37. , m_height{ height }
  38. {
  39. m_cells.resize(m_width);
  40. for (auto& column : m_cells) {
  41. column.resize(m_height);
  42. }
  43. }
  44. template <typename T>
  45. void Grid<T>::verifyCoordinate(size_t x, size_t y) const
  46. {
  47. if (x >= m_width) {
  48. throw std::out_of_range{ std::format("{} must be less than {}.", x, m_width) };
  49. }
  50. if (y >= m_height) {
  51. throw std::out_of_range{ std::format("{} must be less than {}.", y, m_height) };
  52. }
  53. }
  54. template <typename T>
  55. const std::optional<T>& Grid<T>::at(size_t x, size_t y) const
  56. {
  57. verifyCoordinate(x, y);
  58. return m_cells[x][y];
  59. }
  60. template <typename T>
  61. std::optional<T>& Grid<T>::at(size_t x, size_t y)
  62. {
  63. return const_cast<std::optional<T>&>(std::as_const(*this).at(x, y));
  64. }
  1. //GridString.cppm
  2. module;
  3. #include <cstddef>
  4. export module grid:string;
  5. import <stdexcept>;
  6. import <vector>;
  7. import <optional>;
  8. import <utility>;
  9. import <string>;
  10. import <format>;
  11. // When the template specialization is used, the original template must be
  12. // visible too.
  13. import :main;
  14. export
  15. template <>
  16. class Grid<const char*>
  17. {
  18. public:
  19. explicit Grid(size_t width = DefaultWidth, size_t height = DefaultHeight);
  20. virtual ~Grid() = default;
  21. // Explicitly default a copy constructor and copy assignment operator.
  22. Grid(const Grid& src) = default;
  23. Grid& operator=(const Grid& rhs) = default;
  24. // Explicitly default a move constructor and move assignment operator.
  25. Grid(Grid&& src) = default;
  26. Grid& operator=(Grid&& rhs) = default;
  27. std::optional<std::string>& at(size_t x, size_t y);
  28. const std::optional<std::string>& at(size_t x, size_t y) const;
  29. size_t getHeight() const { return m_height; }
  30. size_t getWidth() const { return m_width; }
  31. static const size_t DefaultWidth{ 10 };
  32. static const size_t DefaultHeight{ 10 };
  33. private:
  34. void verifyCoordinate(size_t x, size_t y) const;
  35. std::vector<std::vector<std::optional<std::string>>> m_cells;
  36. size_t m_width{ 0 }, m_height{ 0 };
  37. };
  38. Grid<const char*>::Grid(size_t width, size_t height)
  39. : m_width{ width }
  40. , m_height{ height }
  41. {
  42. m_cells.resize(m_width);
  43. for (auto& column : m_cells) {
  44. column.resize(m_height);
  45. }
  46. }
  47. void Grid<const char*>::verifyCoordinate(size_t x, size_t y) const
  48. {
  49. if (x >= m_width) {
  50. throw std::out_of_range{ std::format("{} must be less than {}.", x, m_width) };
  51. }
  52. if (y >= m_height) {
  53. throw std::out_of_range{ std::format("{} must be less than {}.", y, m_height) };
  54. }
  55. }
  56. const std::optional<std::string>& Grid<const char*>::at(size_t x, size_t y) const
  57. {
  58. verifyCoordinate(x, y);
  59. return m_cells[x][y];
  60. }
  61. std::optional<std::string>& Grid<const char*>::at(size_t x, size_t y)
  62. {
  63. return const_cast<std::optional<std::string>&>(std::as_const(*this).at(x, y));
  64. }
  1. //GridTest.cpp
  2. import <iostream>;
  3. import <string>;
  4. import grid;
  5. using namespace std;
  6. int main()
  7. {
  8. Grid<int> myIntGrid; // Uses original Grid template.
  9. Grid<const char*> stringGrid1{ 2, 2 }; // Uses const char* specialization.
  10. const char* dummy{ "dummy" };
  11. stringGrid1.at(0, 0) = "hello";
  12. stringGrid1.at(0, 1) = dummy;
  13. stringGrid1.at(1, 0) = dummy;
  14. stringGrid1.at(1, 1) = "there";
  15. Grid<const char*> stringGrid2{ stringGrid1 };
  16. cout << stringGrid1.at(0, 1).value_or("") << endl;
  17. cout << stringGrid2.at(0, 1).value_or("") << endl;
  18. }

代码包含网格结构,它执行专门化,以获得工作网格和模块cpp中的测试。

wbgh16ku

wbgh16ku1#

我使用选项编译作为内部分区,而不是接口
使用/interface而不是内部分区。您可能误解了/接口。https://learn.microsoft.com/en-us/cpp/build/reference/interface?view=msvc-170
当模块接口的扩展名不同于. ixx时,请使用此开关。
在下面的示例中,模块接口的扩展名为.cppm而不是.ixx,因此/interface开关用于将其编译为模块接口:

相关问题