我正在学习模板并编写Vector,Vector中有一个构造函数:
template <typename InputIterator>
Vector(typename __isInputIterator<InputIterator>::__result, typename __isInputIterator<InputIterator>::__result, const allocator &);
模板结构__isInputIterator:
struct InputIterator {
constexpr static bool isInputIterator {true};
//...
}
template <typename, bool>
struct __InputIteratorInferringAuxiliary {
using __type = __falseType;
};
template <typename Iterator>
struct __InputIteratorInferringAuxiliary<Iterator, true> {
using __type = Iterator;
};
template <typename Iterator>
struct __isInputIterator {
using __result = typename __InputIteratorInferringAuxiliary<Iterator,
__IteratorTraits<Iterator>::iteratorTag::isInputIterator
>::__type;
};
template <typename T>
struct __IteratorTraits<T *> {
using sizeType = unsigned long;
using differenceType = long;
using valueType = T;
using reference = valueType &;
using constReference = const valueType &;
using rightValueReference = valueType &&;
using pointer = valueType *;
using constPointer = const valueType *;
using iteratorTag = RandomAccessIterator;//isInputIterator tag in RandomAccessIterator class is true
};
演示:
int arr[] {1, 2, 3};
Vector<int> vec(begin(arr), end(arr));//candidate template ignored: couldn't infer template argument 'InputIterator'
为什么编译器会说候选模板被忽略:无法推断模板参数'InputIterator'
非常感谢!
答案 0 :(得分:2)
InputIterator
中的 __isInputIterator<InputIterator>::__result
,因为它处于不可推断的上下文中。
根据CPP工作草案(N4713)中的“从类型推导模板参数”部分:
17.9.2.5从类型推导模板参数
...
在大多数情况下,用于构成P的类型,模板和非类型值会参与模板参数推导。也就是说,它们可用于确定模板参数的值,并且如果这样确定的值与其他地方确定的值不一致,则模板参数推导将失败。 但是,在某些情况下,该值不参与类型推导,而是使用在其他位置推导或明确指定的模板参数的值。 如果模板参数仅在未推导的上下文中使用并且未明确指定,则模板参数推导将失败。
非推论上下文为:
(5.1)— 使用限定ID指定的类型的嵌套名称说明符。
答案 1 :(得分:2)
[问题中的代码既不可少也不可复制。]
问题在于类型cls<T>::type
的参数不可推导。这是您所拥有的确切模式:
template <typename InputIterator>
Vector(typename __isInputIterator<InputIterator>::__result, typename __isInputIterator<InputIterator>::__result, const allocator &);
您只需重新构造构造函数,使其可推论:
template <typename InputIterator,
typename __isInputIterator<InputIterator>::__result* = nullptr>
Vector(InputIterator, InputIterator, const allocator & = allocator{});
这样,InputIterator是可推断的,并且其有效性通过默认参数进行测试。这仍然不能满足您的要求,因为在您的部分代码__isInputIterator<InputIterator>::__result
中始终将其定义为某些内容。您想要的东西是SFINAE,即仅当这是输入迭代器时才定义,否则则未定义。您想要类似std::enable_if
的内容:
template <typename InputIterator,
std::enable_if_t<__isInputIterator<InputIterator>::__result::value>* x = nullptr>
Vector(InputIterator, InputIterator, const allocator & = allocator{});
__
)前缀的名称,因为这些名称是为编译器保留的。
#include <memory>
#include <type_traits>
struct InputIterator {
constexpr static bool isInputIterator {true};
//...
};
struct __falseType
{
static constexpr bool value{false};
};
struct __trueType
{
static constexpr bool value{true};
};
template <typename, bool>
struct __InputIteratorInferringAuxiliary {
using __type = __falseType;
};
template <typename Iterator>
struct __InputIteratorInferringAuxiliary<Iterator, true> {
using __type = __trueType;
};
struct NotIterator {
static constexpr bool isInputIterator = false;
};
template <typename T>
struct __IteratorTraits {
using iteratorTag = NotIterator;
};
struct RandomAccessIterator {
static constexpr bool isInputIterator = true;
};
template <typename T>
struct __IteratorTraits<T *> {
using sizeType = unsigned long;
using differenceType = long;
using valueType = T;
using reference = valueType &;
using constReference = const valueType &;
using rightValueReference = valueType &&;
using pointer = valueType *;
using constPointer = const valueType *;
using iteratorTag = RandomAccessIterator;//isInputIterator tag in RandomAccessIterator class is true
};
template <typename Iterator>
struct __isInputIterator {
using __result = typename __InputIteratorInferringAuxiliary<Iterator,
__IteratorTraits<Iterator>::iteratorTag::isInputIterator
>::__type;
};
template <class T, class allocator=std::allocator<T>>
class Vector
{
public:
template <typename InputIterator,
std::enable_if_t<__isInputIterator<InputIterator>::__result::value>* x = nullptr>
Vector(InputIterator, InputIterator, const allocator & = allocator{});
T* begin();
T* end();
};
int main()
{
int arr[] {1, 2, 3};
Vector<int> vec(std::begin(arr), std::end(arr));//candidate template ignored: couldn't infer template argument 'InputIterator'
Vector<int> vec2(1,2);//candidate template ignored: couldn't infer template argument 'InputIterator'
}