if-else 后缺少 return 语句
Missing return statement after if-else
一些编译器(Intel icc,pgi/nvc++)对下面的函数发出“缺少 return 语句”警告,而其他编译器(gcc,clang)即使使用 -Wall -Wextra -pedantic
:
根据标准,下面的代码是否合法?
这是我的代码中发出警告的最小可重现示例。将其简化为仅一个函数即可删除警告。
// test.cpp
#include <climits>
#include <cstddef>
template<class T, std::size_t N>
class Test
{
public:
class Inner;
private:
static constexpr std::size_t NB_ = sizeof(std::size_t) * CHAR_BIT;
static constexpr std::size_t NI_ = (N + NB_ - 1) / NB_;
};
template<class T, std::size_t N>
class Test<T, N>::Inner
{
public:
Inner() : b_{0}, j_{0} {}
friend bool operator!= (Inner x, Inner y)
{
if constexpr(J_ > 0)
return x.j_ != y.j_ || x.b_ != y.b_;
else
return x.b_ != y.b_;
}
private:
static constexpr std::size_t J_ = NI_ - 1;
std::size_t b_;
std::size_t j_;
};
int main()
{
Test<int, 50>::Inner x, y;
int a, b;
x.b_ = a; y.b_ = b;
x != y;
}
编译:
> nvc++ test.cpp -std=c++17
"test.cpp", line 30: warning: missing return statement at end of non-void function "operator!="
}
^
detected during instantiation of class "Test<T, N>::Inner [with T=int, N=50UL]" at line 41
能否将这些项目设置为编译为早期的 C++ 标准?
一些较旧的编译器不喜欢代码块中间的 returns(还有一些编译器不喜欢代码块开头以外的任何地方的变量标识符)。
对于那些抱怨的人,我只是编码为:
ret_type f(...)
{
ret_type result = DEFAULT_VALUE; //default value defined elsewhere
if (condition)
result = value_1; //presumed valid ret_type value
else
result = value_2; //presumed valid ret_type value
return result;
}
C++ 标准是这样说的,参见 [stmt.return]/2:
Flowing off the end of a constructor, a destructor, or a function with a cv void
return type is equivalent to a return
with no operand. Otherwise, flowing off the end of a function other than main
results in undefined behavior.
您的 operator !=
正是这样做的。它永远不会流出函数的末尾,因为所有控制路径都以 return
.
结尾
因此代码是正确的,编译器的诊断是错误的。
我有一些功能,其中只有特定的结果是可接受的,以便 return
,您的设置是怎样的。如果它确实是一个小众案例,其中两个 if
语句都是错误的(强调小众),那么就会有问题并且可以抛出异常。
在我的例子中,在最后一个 if
子句之后,我添加:
throw std::invalid_argument("\nx and y cannot be compared\n)");
要让您的代码在没有警告的情况下进行编译 (Intel ICC 2021.3.0),请使用 __builtin_unreachable()
告诉编译器控制流永远不会结束:
friend bool operator!= (Inner x, Inner y)
{
if constexpr(J_ > 0)
return x.j_ != y.j_ || x.b_ != y.b_;
else
return x.b_ != y.b_;
__builtin_unreachable();
}
一些编译器(Intel icc,pgi/nvc++)对下面的函数发出“缺少 return 语句”警告,而其他编译器(gcc,clang)即使使用 -Wall -Wextra -pedantic
:
根据标准,下面的代码是否合法?
这是我的代码中发出警告的最小可重现示例。将其简化为仅一个函数即可删除警告。
// test.cpp
#include <climits>
#include <cstddef>
template<class T, std::size_t N>
class Test
{
public:
class Inner;
private:
static constexpr std::size_t NB_ = sizeof(std::size_t) * CHAR_BIT;
static constexpr std::size_t NI_ = (N + NB_ - 1) / NB_;
};
template<class T, std::size_t N>
class Test<T, N>::Inner
{
public:
Inner() : b_{0}, j_{0} {}
friend bool operator!= (Inner x, Inner y)
{
if constexpr(J_ > 0)
return x.j_ != y.j_ || x.b_ != y.b_;
else
return x.b_ != y.b_;
}
private:
static constexpr std::size_t J_ = NI_ - 1;
std::size_t b_;
std::size_t j_;
};
int main()
{
Test<int, 50>::Inner x, y;
int a, b;
x.b_ = a; y.b_ = b;
x != y;
}
编译:
> nvc++ test.cpp -std=c++17
"test.cpp", line 30: warning: missing return statement at end of non-void function "operator!="
}
^
detected during instantiation of class "Test<T, N>::Inner [with T=int, N=50UL]" at line 41
能否将这些项目设置为编译为早期的 C++ 标准?
一些较旧的编译器不喜欢代码块中间的 returns(还有一些编译器不喜欢代码块开头以外的任何地方的变量标识符)。
对于那些抱怨的人,我只是编码为:
ret_type f(...)
{
ret_type result = DEFAULT_VALUE; //default value defined elsewhere
if (condition)
result = value_1; //presumed valid ret_type value
else
result = value_2; //presumed valid ret_type value
return result;
}
C++ 标准是这样说的,参见 [stmt.return]/2:
Flowing off the end of a constructor, a destructor, or a function with a cv
void
return type is equivalent to areturn
with no operand. Otherwise, flowing off the end of a function other thanmain
results in undefined behavior.
您的 operator !=
正是这样做的。它永远不会流出函数的末尾,因为所有控制路径都以 return
.
因此代码是正确的,编译器的诊断是错误的。
我有一些功能,其中只有特定的结果是可接受的,以便 return
,您的设置是怎样的。如果它确实是一个小众案例,其中两个 if
语句都是错误的(强调小众),那么就会有问题并且可以抛出异常。
在我的例子中,在最后一个 if
子句之后,我添加:
throw std::invalid_argument("\nx and y cannot be compared\n)");
要让您的代码在没有警告的情况下进行编译 (Intel ICC 2021.3.0),请使用 __builtin_unreachable()
告诉编译器控制流永远不会结束:
friend bool operator!= (Inner x, Inner y)
{
if constexpr(J_ > 0)
return x.j_ != y.j_ || x.b_ != y.b_;
else
return x.b_ != y.b_;
__builtin_unreachable();
}