I can't understand why the following code doesn't compile. The error message given by the compiler isn't that helpful either.
Working example:
#include <string>
#include <type_traits>
template <typename T>
struct TIteratorValue {
using Type = typename T::Type;
};
template <typename T>
struct TIteratorValue<T *> {
using Type = T;
};
template <typename T>
using IteratorValue = typename TIteratorValue<T>::Type;
template <typename T>
struct Test {
template <typename V,
std::enable_if_t<std::is_constructible_v<T, V>, int> = 0>
Test(std::initializer_list<V> const list, size_t const x = 0)
: Test(list.begin(), list.end(), x) {}
template <typename I,
std::enable_if_t<std::is_constructible_v<T, IteratorValue<I>>, int> = 0>
// Does not compile!
Test(I begin, I const end, size_t const x = 0) {}
// Compiles!
//Test(I begin, I const end, size_t const x) {}
};
int
main() {
Test<std::string> test({ "a", "b", "c" }, 10);
return 0;
}
Clang's error message:
C:\Users\joaom\Dropbox\++A\so\weird_overloading.cpp:6:24: error: type 'int' cannot be used prior to '::' because it has no members
using Type = typename T::Type;
^
C:\Users\joaom\Dropbox\++A\so\weird_overloading.cpp:15:1: note: in instantiation of template class 'TIteratorValue<int>' requested here
using IteratorValue = typename TIteratorValue<T>::Type;
^
C:\Users\joaom\Dropbox\++A\so\weird_overloading.cpp:25:50: note: in instantiation of template type alias 'IteratorValue' requested here
std::enable_if_t<std::is_constructible_v<T, IteratorValue<I>>, int> = 0>
^
C:\Users\joaom\Dropbox\++A\so\weird_overloading.cpp:27:2: note: while substituting prior template arguments into non-type template parameter
[with I = int]
Test(I begin, I const end, size_t const x = 0) {}
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\joaom\Dropbox\++A\so\weird_overloading.cpp:35:20: note: while substituting deduced template arguments into function template 'Test'
[with I = int, $1 = (no value)]
Test<std::string> test({ "a", "b", "c" }, 10);
The only int
is the argument x
but I can't see how's that affecting the code. Visual Studio gives me the same error too.
template <typename I, std::enable_if_t<std::is_constructible_v<T, IteratorValue<I>>, int> = 0>
// Does not compile!
Test(I begin, I const end, size_t const x = 0) {}
// Compiles!
//Test(I begin, I const end, size_t const x) {}
Both of these functions will not compile if the template is instantiated.
Since your main
function attempts to construct a Test
from 2 parameters, adding a default value to the third parameter simply means that this function should be considered. It allows the template to be instantiated.
I still can't understand why the following code doesn't compile.
You are defining IteratorValue<I>
(and therefore I::type
) before checking if I
is an iterator.
Use the already defined std::iterator_traits
to solve this.
// Formatted for clarity
template <typename I,
std::enable_if_t<
std::is_constructible_v<
T,
typename std::iterator_traits<I>::value_type
>,
int
> = 0>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.