为什么编译器说"candidate template ignored: couldn't infer template argument 'InputIterator'"?
Why compiler said "candidate template ignored: couldn't infer template argument 'InputIterator'"?
我正在学习模板并编写 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'
为什么编译器会说候选模板被忽略:无法推断模板参数"输入迭代器">
多谢!
[问题中的代码既不是最小的,也不是可重现的。
问题是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{});
这样,输入迭代器是可推导的,其有效性由默认参数测试。这仍然不会做你想要的,因为在部分代码中,__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'
}
__isInputIterator<InputIterator>::__result
中的InputIterator
无法推断,因为它处于不可推导的上下文中。
根据CPP工作草案(N4713(中关于"从类型推断模板参数"的部分:
17.9.2.5 从类型推导模板参数...
大多数情况下,用于组成 P 的类型、模板和非类型值参与模板参数推导。也就是说,它们可用于确定模板参数的值,如果这样确定的值与其他地方确定的值不一致,则模板参数推导失败。 但是,在某些上下文中,该值不参与类型推断,而是使用在其他地方推导或显式指定的模板参数的值。如果模板参数仅在非推导上下文中使用,并且未显式指定,则模板参数推导失败。
非推导上下文是:
(5.1( —使用限定 id 指定的类型的嵌套名称说明符。
相关文章:
- 表示"accepting anything for this template argument" C++概念的通配符
- 为什么编译器说"candidate template ignored: couldn't infer template argument 'InputIterator'"?
- 实现多类型算术运算符时如何解决"template argument deduction/substitution failure"
- 如何修复 eigen3 中的'non-type template argument is not a constant expression'?
- 通过"Value Template Argument"与常规阵列在堆栈中分配内存
- 模板类错误的向量:"Template argument 2 is invalid"
- 如何修复"static assertion failed: template argument not an integral type"错误?
- 如何在返回类型函数模板的专用化中使用派生类型?( "couldn't infer template argument" )
- "could not convert template argument"到自己的类型
- 表达式模板:错误 C2784 'could not deduce template argument'
- 需要帮助理解 GCC 给出"within a nested template argument list"错误的含义
- constexpr with std::array - "Non-type template argument is not a constant expression"
- "unspecialized class template can't be used as a template argument"是什么意思?
- MSVC:"use of class template requires template argument list" STL 容器内
- "missing template argument"是什么意思?
- std::map.insert "could not deduce template argument for..."
- "template argument deduction for class templates"是否应该推断出可变参数类模板的空参数包?
- 为什么此代码有 C2784 "could not deduce template argument"错误
- 即使使用强制转换,指针参数也"could not convert template argument"错误
- "use of class template requires template argument list"错误,即使使用了模板的模板,因此模板类是预期的