【问题标题】:Why does automatic type deduction not work for constexpr member referencing?为什么自动类型推导不适用于 constexpr 成员引用?
【发布时间】:2022-01-03 09:51:03
【问题描述】:

在示例代码中,用 C++17 编译:

template <typename T = int>
struct A
{
    static constexpr double b = 0.5;
};

int main()
{
    A a;  // compiles
    double c = A<>::b; // compiles
    double d = A::b; // fails to compile
    // ...
    return 0;
}

Live example

A::b 编译失败,因为:

main.cpp:13:16: error: 'template<class T> struct A' used without template arguments
   13 |     double d = A::b; // fails to compile

我认为在 C++17 中自动模板类型推导会解决这个问题,因为我有默认模板参数。我错过了什么?

【问题讨论】:

  • 哪个编译器?
  • @kiner_shah 在 catkin 中编译,所以 gcc 带有一些 ros 版本。大概g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
  • 但现场示例也能做到这一点,即版本:g++ (GCC) 11.2.0

标签: c++ templates c++17


【解决方案1】:

每个实例化的类实例都有自己的A&lt;T&gt;::b 成员。

#include <iostream>

template <typename T = int>
struct A
{
    static constexpr double b = 0.5;
};

int main()
{
    std::cout << &A<int>::b << "\n"; 
    std::cout << &A<char>::b << "\n"; 
    return 0;
}

使用 clang++13 编译,带有选项 -std=c++17。输出:

0x402008
0x402018

想想A::b是否可以编译,编译器会选择哪个地址。

活生生的例子https://godbolt.org/z/GqhjMvoz6

至于使用默认模板参数编译double d = A::b;失败,这是规则,模板必须实例化使用尖括号&lt;, &gt;

【讨论】:

  • 好吧,从技术角度来看这是有道理的,但是当编译器通过时,它肯定会替换值并且不会有地址正确(至少在 -O3 优化中)?
  • 即使使用 -O3,地址仍然不同。我想它来自 C++ 直到 C++17 需要静态成员的定义,请参阅stackoverflow.com/questions/8016780/…。如果不请求 constexpr 值的地址,则它们可能根本不存在/不放置在内存中。
猜你喜欢
  • 2020-05-05
  • 1970-01-01
  • 2016-11-14
  • 2022-11-16
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多