constexpr 函数中存在 C++ Wconversion 警告,但模板中没有

标签 c++ templates constexpr

我的问题是,为什么以下代码针对 constexpr 函数生成警告,而不针对模板生成警告?

我确实了解警告的含义以及如何消除它们。我不明白的是为什么编译器不为 struct Testconstexpr 成员 ToDoubleToSquare 生成警告> 下面?

#include <iostream>

template <typename T, T value>
struct Test {
  static constexpr double ToDouble = value;

  static constexpr T ToSquare = value * value;
};

template <typename T>
constexpr double ToDouble(T value) {
  return value;
}

template <typename T>
constexpr T ToSquare(T value) {
  return value * value;
}

int main() {
  std::cout << Test<long, 1>::ToDouble << std::endl;
  std::cout << ToDouble(static_cast<long>(1)) << std::endl;

  std::cout << Test<char, 1>::ToSquare << std::endl;
  std::cout << ToSquare(static_cast<char>(1)) << std::endl; 
}
$ g++ -Wconversion -std=c++11 a.cc 
a.cc: In instantiation of ‘constexpr double ToDouble(T) [with T = long int]’:
a.cc:22:45:   required from here
a.cc:12:10: warning: conversion to ‘double’ from ‘long int’ may alter its value [-Wconversion]
   return value;
      ^~~~~
a.cc: In instantiation of ‘constexpr T ToSquare(T) [with T = char]’:
a.cc:25:45:   required from here
a.cc:17:16: warning: conversion to ‘char’ from ‘int’ may alter its value [-Wconversion]
   return value * value;

最佳答案

模板生成一个类型。在该类型的每个实例中,值 value 是一个编译时常量。并且它可以检查精度损失。

constexpr情况下,模板函数的生成函数没有此属性。不保证参数 value 是编译时常量。虽然您仅在它是编译时常量的上下文中使用它,但警告不会检查每个调用上下文。

可能你误解了constexpr;在函数上,它声明函数可以在编译时求值,而不是必须

关于constexpr 函数中存在 C++ Wconversion 警告,但模板中没有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52567897/

相关文章:

c++ - Python 等效于 std::set 和 std::multimap

wpf - DataTemplateSelector 不会被使用

c++ - 通过在 constexpr 构造函数中传递 N 在编译时创建大小为 N 的数组

c++ - 评估不同参数的 constexpr 函数时的运行时差异

c++ - volatile 与内存栅栏

c++ - 在指向(全局/持久)对象的指针超出范围后,对象(不是指针)的成员 vector 获取 'unset'

c++ - 为什么 const int 适合 char 大括号 init?

c++ - 传递给模板函数的可变参数模板

c++ - 如何用sfinae检查,type是否有operator()?

c++ - constexpr std::optional 重置