C++ 为什么我可以在MSVC和icc中为glm::vec创建用户定义的结构化绑定,而不是Clang和GCC?

C++ 为什么我可以在MSVC和icc中为glm::vec创建用户定义的结构化绑定,而不是Clang和GCC?,c++,gcc,visual-c++,c++17,glm-math,C++,Gcc,Visual C++,C++17,Glm Math,在过去一年左右的时间里,我一直在MSVC项目中使用类似于以下内容的代码,但在试图将其用于g++时遇到了一个问题 #include <utility> #include <glm/glm.hpp> namespace std { template< std::size_t I, auto N, class T, auto Q> constexpr auto& get(glm::vec<N, T, Q>& v) noexcep

在过去一年左右的时间里,我一直在MSVC项目中使用类似于以下内容的代码,但在试图将其用于g++时遇到了一个问题

#include <utility>
#include <glm/glm.hpp>

namespace std {
  template< std::size_t I, auto N, class T, auto Q>
  constexpr auto& get(glm::vec<N, T, Q>& v) noexcept { return v[I]; }

  template< std::size_t I, auto N, class T, auto Q>
  constexpr const auto& get(const glm::vec<N, T, Q>& v) noexcept { return v[I]; }

  template< std::size_t I, auto N, class T, auto Q>
  constexpr auto&& get(glm::vec<N, T, Q>&& v) noexcept { return std::move(v[I]); }

  template< std::size_t I, auto N, class T, auto Q>
  constexpr const auto&& get(const glm::vec<N, T, Q>&& v) noexcept { return std::move(v[I]); }

  template <auto N, class T, auto Q>
  struct tuple_size<glm::vec<N, T, Q>> : std::integral_constant<std::size_t, N> { };

  template <std::size_t I, auto N, class T, auto Q>
  struct tuple_element<I, glm::vec<N, T, Q>> {
    using type = decltype(get<I>(declval<glm::vec<N,T,Q>>()));
  };
}// end std


auto f(){
  auto [x,y,z] = glm::vec3(1);
  return x + y + z;
}

#包括
#包括
名称空间标准{
模板
constexpr auto&get(glm::vec&v)noexcept{return v[I];}
模板
constexpr const auto&get(const glm::vec&v)noexcept{return v[I];}
模板
constexpr auto&&get(glm::vec&&v)noexcept{return std::move(v[I]);}
模板
constexpr const auto&&get(const glm::vec&&v)noexcept{return std::move(v[I]);}

模板

我相信GCC和Clang是正确的

下面是关于结构化绑定的说明:

表达式
std::tuple\u size::value
必须是格式正确的整数常量表达式

对于每个标识符,将引入一个类型为“reference to
std::tuple\u element::type
”的变量……第i个变量的初始值设定项为

  • e.get()
    ,如果按类成员访问查找
    e
    范围内的标识符
    get
    ,则至少会找到一个声明,该声明是其第一个模板参数为非类型参数的函数模板
  • 否则,
    get(e)
    其中
    get
    仅通过依赖参数的查找进行查找,忽略非ADL查找
(强调矿山)


您必须将您的
get()
重载移动到
名称空间glm

哇,谢谢!我想知道为什么类似的东西会起作用,但我的第一个示例不会。我想当我最初编写代码时,我移动了
get()
重载到
std
,因为它在其他情况下不起作用。但我从未真正尝试弄清楚到底发生了什么。