std::initializer_list的怪异构造函数SFINAE错误



我不明白为什么下面的代码不能编译。编译器给出的错误信息也没有多大帮助。

工作的例子:

#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的错误信息:

C:UsersjoaomDropbox++Asoweird_overloading.cpp:6:24: error: type 'int' cannot be used prior to '::' because it has no members     
using Type = typename T::Type;
^
C:UsersjoaomDropbox++Asoweird_overloading.cpp:15:1: note: in instantiation of template class 'TIteratorValue<int>' requested here
using IteratorValue = typename TIteratorValue<T>::Type;
^
C:UsersjoaomDropbox++Asoweird_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:UsersjoaomDropbox++Asoweird_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:UsersjoaomDropbox++Asoweird_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);

唯一的int是参数x,但我看不出这是如何影响代码的。Visual Studio也给了我同样的错误。

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) {}

不能编译

由于您的main函数试图从2个参数构造Test,因此向第三个参数添加默认值仅仅意味着应该考虑该函数。它允许模板实例化。

我还是不明白为什么下面的代码不能编译。

在之前定义IteratorValue<I>(因此I::type)检查I是否为迭代器

使用已经定义的std::iterator_traits来解决这个问题。

// Formatted for clarity
template <typename I,
std::enable_if_t<
std::is_constructible_v<
T,
typename std::iterator_traits<I>::value_type
>,
int
> = 0>

最新更新