Reputation: 53
I am defining a constructors of a class that constrained to check for the type equivalence of the underlying type of passed-in iterator versus the node_type defined in my class, with the help of concepts or SFINAE.
However, tried a few combinations with is_same<>, is_same_v<>, enable_if<>
, and same_as<>
concept, the out-of-line definition will always yield compile time errors on at least one of the major compilers. Currently below snippet sees no error on MSVC/g++, but clang complains, all using latest version(19.28, 11.1, 12.0 respectively). Can anyone clarify what is wrong here? Thanks.
Edited:
As of GCC 12 and Clang 14, this bug persists.
Code as below on godbolt using C++20, MSVC/g++ ok, clang error https://godbolt.org/z/fdqEYxKh8
Code not shown below but on godbolt using C++11 SFINAE, MSVC/clang ok, g++ error https://godbolt.org/z/7nr7a8jY8
#include <stdio.h>
#include <iterator>
#include <array>
#include <concepts>
#include <cstdlib>
template <typename FPType, std::size_t N>
class PointND {
private:
std::array<FPType, N> coords_;
};
template <typename FPType, std::size_t N, typename ElemType>
class Tree {
public:
struct node_type {
PointND<FPType, N> key;
ElemType value;
};
template <std::random_access_iterator RAI>
requires std::same_as<typename std::iterator_traits<RAI>::value_type,
typename Tree<FPType, N, ElemType>::node_type>
Tree(RAI, RAI);
};
template <typename FPType, std::size_t N, typename ElemType>
template <std::random_access_iterator RAI>
requires std::same_as<typename std::iterator_traits<RAI>::value_type,
typename Tree<FPType, N, ElemType>::node_type>
Tree<FPType, N, ElemType>::Tree(RAI begin, RAI end) {
}
Error on this line::45:30: error: out-of-line definition of 'Tree<FPType, N, ElemType>' does not match any declaration in 'Tree<FPType, N, ElemType>'
Tree<FPType, N, ElemType>::Tree(RAI begin, RAI end) {
Upvotes: 1
Views: 372
Reputation: 7528
On the C++11 example, add -fchecking
and gcc will say:
<source>:52:51: internal compiler error: canonical types differ for identical types 'std::enable_if<(std::is_same<typename std::iterator_traits<_InputIterator>::iterator_category, std::random_access_iterator_tag>::value && std::is_same<typename std::iterator_traits<_InputIterator>::value_type, typename Tree<FPType, N, ElemType>::node_type>::value), int>' and 'std::enable_if<(std::is_same<typename std::iterator_traits<_InputIterator>::iterator_category, std::random_access_iterator_tag>::value && std::is_same<typename std::iterator_traits<_InputIterator>::value_type, Tree<FPType, N, ElemType>::node_type>::value), int>'
52 | Tree<FPType, N, ElemType>::Tree(RAI begin, RAI end) {
| ^
...
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
gcc's failure to compile this is a compiler bug.
I suspect but cannot prove that clang's behavior on the C++20 code is also a bug.
There is an easy workaround. These bugs have to do with interpreting names, particularly a nested class, inside the context of an incomplete class. So... move the type to namespace scope:
Upvotes: 0