I have a C++14 project that I'm developing on CLion 2016.3.4, and one snippet of code was giving me inspection errors. I created a bare minimum code to reproduce the problem:
#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 gives me Call to "error_enum_to_int" is ambiguous
for every call occurrence of error_enum_to_int
. Is there really something wrong with that kind of use?
Some things I tried, but that are not really fixes IMHO:
- Delete the declaration, and leave only the definition (works, but I wanted to keep them at different locations in the same compilation unit, if posible);
- Delete the SFINAE template argument (works, but then it'll work for every type, and that's not my intention);
- Substitute the
T
argument byenable_if_condition_enum_t<T>
(does not work, gives me a whole new set of compilation and inspection errors).
Also, the code compiles and runs just fine, without any fix, on g++ (GCC) 6.3.1 20170306
. Unfortunately, I have no access to another compiler to test this out right now, but I'd guess this is standard, portable C++11.
Of course, there's always the option to static_cast<some_enum_class>(some_int)
, but I want to know specifically what may be possibly wrong with this snippet of code.
So, my question is: is this a bug of my IDE, is there really some corner case of the language I'm not aware of or am I really doing something stupid here (:D)?
My reasoning
Please correct me if I'm wrong.
A declaration by itself is not a definition, even if it's a function template. A function template, by itself, is not really a function until it's instantiated. Even so, the compiler should be able to see that there're two different occurrences of the same function template and not confuse one for the other, as long as both are present in the same compilation/translation unit. The way I see it is that CLion (or perhaps clang's static analyzer) somehow considers the declaration as a definition and interprets them to be different things. And as both are templates, it becomes confused as to which one to instantiate.
Note that both the declaration and the definition are present on the same compilation unit. Also, constexpr
implies inline
, so the one definition rule still applies. Moreover, I use enable_if_condition_enum_t
for SFINAE-based elimination, if the enum being used as an argument is not declared as an std::error_condition
enum.
Aucun commentaire:
Enregistrer un commentaire