- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个在 CLion 2016.3.4 上开发的 C++14 项目,一段代码给我检查错误。我创建了一个最低限度的代码来重现该问题:
#include <iostream>
#include <type_traits>
#include <system_error>
using error_id_type = int;
template <typename T> using enable_if_condition_enum_t =
typename std::enable_if<std::is_error_condition_enum<T>::value, T>::type;
// Declaration
template <typename T, typename = enable_if_condition_enum_t<T>>
constexpr error_id_type error_enum_to_int(T elem) noexcept;
// Definition
template <typename T, typename = enable_if_condition_enum_t<T>>
constexpr error_id_type error_enum_to_int(T elem) noexcept {
return static_cast<error_id_type>(elem);
};
int main(void) {
error_id_type condition = error_enum_to_int(std::errc::owner_dead); // inspection error here
switch (condition) {
case error_enum_to_int(std::errc::address_in_use): break; // inspection error here
default: break;
}
std::cout << condition << std::endl;
return 0;
}
CLion 给我 Call to "error_enum_to_int" is ambiguous
对于 error_enum_to_int
的每次调用.这种用法真的有问题吗?
一些我尝试过的东西,但恕我直言,这并不能真正解决问题:
T
enable_if_condition_enum_t<T>
的争论(不起作用,给我一整套新的编译和检查错误)。此外,代码在 g++ (GCC) 6.3.1 20170306
上编译和运行得很好,没有任何修复。 .不幸的是,我现在无法访问另一个编译器来测试它,但我猜这是标准的、可移植的 C++11。
当然,始终可以选择 static_cast<some_enum_class>(some_int)
,但我想具体了解这段代码可能有什么问题。
所以,我的问题是:这是我的 IDE 的错误吗,是否真的存在我不知道的语言的一些特殊情况,或者我真的在这里做了一些愚蠢的事情 (:D)?
如有错误请指正
声明本身不是定义,即使它是一个函数模板。函数模板本身在被实例化之前并不是真正的函数。即便如此,编译器应该能够看到同一个函数模板有两次不同的出现,并且不会将一个与另一个混淆,只要两者都存在于同一个编译/翻译单元中。我的看法是 CLion(或者可能是 clang 的静态分析器)以某种方式将声明视为定义并将它们解释为不同的东西。由于两者都是模板,因此对于实例化哪一个变得很困惑。
请注意,声明和定义都出现在同一个编译单元中。另外,constexpr
暗示 inline
,所以单一定义规则仍然适用。此外,我使用 enable_if_condition_enum_t
对于基于 SFINAE 的消除,如果用作参数的枚举未声明为 std::error_condition
枚举。
正在关注 @Angew's answer , 这是 error_enum_to_int
的正确声明和定义.
// Declaration
template <typename T, typename = enable_if_condition_enum_t<T>>
constexpr error_id_type error_enum_to_int(T elem) noexcept;
// Definition
template <typename T, typename>
constexpr error_id_type error_enum_to_int(T elem) noexcept {
return static_cast<error_id_type>(elem);
};
最佳答案
在 C++ 中,您不能为同一参数/模板参数多次提供默认参数或默认模板参数。来自函数所有声明(包括定义)的默认 [template] 参数被组合(级联)。您应该从模板的定义中删除默认模板参数。
关于c++ - SFINAE 消除、Constexpr 和函数模板 : Can I keep declaration and definition separate?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42891055/
我是一名优秀的程序员,十分优秀!