C++ 施工人员的优先权c++;

C++ 施工人员的优先权c++;,c++,constructor,iterator,C++,Constructor,Iterator,我遇到了一个很奇怪的问题 对于这样的代码 template <typename T> struct A{ explicit A(unsigned int size = 0, const T &t = T()) { } template <typename InputIterator> A(InputIterator first, InputIterator last)

我遇到了一个很奇怪的问题

对于这样的代码

    template <typename T>
    struct A{
        explicit A(unsigned int size = 0, const T &t = T())
        {
        }
        template <typename InputIterator>
        A(InputIterator first, InputIterator last) {
            for(;first != last ; ++first)
            {
                *first; //do something with iterator
            }
        }
    };
      temp.cpp: In instantiation of ‘A<T>::A(InputIterator, InputIterator) [with = int; T = int]’:
    temp.cpp:17:15:   required from here
    temp.cpp:12:4: error: invalid type argument of unary ‘*’ (have ‘int’)
模板
结构A{
显式A(无符号整数大小=0,常量T&T=T())
{
}
模板
A(先输入,后输入){
for(;first!=last;++first)
{
*首先;//使用迭代器执行某些操作
}
}
};
例如,当我定义

        A<int> a(10,10);
A(10,10);
使用迭代器的第二个构造函数,而不是第一个构造函数。 那么向量构造函数是如何工作的,当它们看起来一样的时候

    explicit vector (size_type n, const value_type& val = value_type(),
             const allocator_type& alloc = allocator_type());

    template <class InputIterator>
     vector (InputIterator first, InputIterator last,
             const allocator_type& alloc = allocator_type());
显式向量(大小\u类型n,常量值\u类型&val=value\u类型(),
常量分配器类型&alloc=allocator类型();
模板
向量(先输入计数器,后输入计数器,
常量分配器类型&alloc=allocator类型();
我可以做向量v(10,10),没有任何问题

PS我犯了这样的错误

    template <typename T>
    struct A{
        explicit A(unsigned int size = 0, const T &t = T())
        {
        }
        template <typename InputIterator>
        A(InputIterator first, InputIterator last) {
            for(;first != last ; ++first)
            {
                *first; //do something with iterator
            }
        }
    };
      temp.cpp: In instantiation of ‘A<T>::A(InputIterator, InputIterator) [with = int; T = int]’:
    temp.cpp:17:15:   required from here
    temp.cpp:12:4: error: invalid type argument of unary ‘*’ (have ‘int’)
temp.cpp:A::A(InputIterator,InputIterator)[with=int;T=int]的实例化中:
温度cpp:17:15:此处需要
临时cpp:12:4:错误:一元“*”的类型参数无效(具有“int”)

编译器在使用
A
时选择第二个构造函数的原因很简单:您的
10
是有符号类型
int
的值,而
size\u类型
是一些无符号整数类型。这意味着
10
必须转换为该无符号整数类型。这种转换的需要使得第一个构造函数失去了第二个构造函数的重载解析(这与
InputIterator=int
完全匹配)。您可以通过执行以下操作来解决此问题

A<int> a(10u, 10);
应具有与以下内容相同的效力:

当然,这可能意味着您最终必须为所有整数类型添加重载

一个更好的解决方案(我已经在上面提到过)是使用
enable\u if
或类似的基于SFINAE的技术禁用整数参数的模板构造函数。比如说

    template <typename InputIterator>
    A(InputIterator first, InputIterator last, 
      typename std::enable_if<!std::is_integral<InputIterator>::value>::type* = 0)
模板
A(先输入,后输入,
typename std::enable_if::value>::type*=0)

您的编译器中有C++11功能吗?

没错,模板化的东西更匹配,因此它被选中。标准库实现努力引导所有模板化成员的合理行为。如果您想要实现自己的类似集合,您可能需要查找一些专门化的实现代码

或者你可以找到一种方法来回避这个问题


有一篇很好的GOTW文章,介绍了函数重载选择的所有情况,并给出了一些解决方法。

你在
a(10,10)
中的第一个参数与显式构造函数不匹配,因为
10
是有符号的,所以它使用了模板化的构造函数。将其更改为
A(10u,10)
,您可能会得到预期的结果。

inputierator
int
时,实例化的

A(int first, int last)
explicit A(unsigned int size = 0, const int &t = int())
比实例化的

A(int first, int last)
explicit A(unsigned int size = 0, const int &t = int())
由于第一个参数是无符号的
A((unsigned int)10,10)
应该调用您期望的构造函数。您还可以使用来防止匹配,除非构造函数确实传递了两个迭代器到
T

#include <iostream>

using namespace std;

template <typename T>
struct A{
    explicit A(unsigned int size = 0, const T &t = T())
    {
        cout << "size constructor for struct A" << endl;
    }

    template <class I>
    using is_T_iterator = typename enable_if<is_same<typename iterator_traits<I>::value_type, T>::value, T>::type;

    template <typename InputIterator>
    A(InputIterator first, InputIterator last,  is_T_iterator<InputIterator> = 0) {
        cout << "iterator constructor for struct A" << endl;
        for(;first != last ; ++first)
        {
            *first; //do something with iterator
        }
    }
};

int main()
{
    A<int>(10,10);

    A<int>((int*)0,(int*)0);

    //A<int>((char*)0,(char*)0); //<-- would cause compile time error since (char *) doesn't dereference to int

    return 0;
}
#包括
使用名称空间std;
模板
结构A{
显式A(无符号整数大小=0,常量T&T=T())
{

cout如果您正在编写一个通用库,您可能希望 额外的努力,并使用模板元编程来捕获所有 或者简单地为所有 整型。对于不太通用的用法,它通常就足够了 遵循以下规则,即任何时候为任何 整数类型,您还为
int
提供了一个 构造函数a::a(int size,T const&initialValue=T())
, 除了您已经提供的以外)

更一般地说:您应该将
size
int
,然后用它来完成。标准库被赶上了 在很多历史问题中,默认情况下必须使用
size\t
, 但总的来说,除非有非常充分的理由这样做 否则,C++中的正规整型是<代码> int <代码>; 此外,C++中的无符号类型具有非常奇怪的语义, 任何时候都应该避免计算
发生的操作。

您指的是哪些规范?参数类型
int,int
的标准真的是特例吗?这让我很惊讶。@KonradRudolph,在N3690中是[sequence.reqmts]/14,“如果构造函数[…]使用不符合输入迭代器条件的类型
inputierator
调用,则构造函数不应参与重载解析。”“一个实现确定一个类型不能成为输入迭代器的程度是未指定的,除非作为最小整数类型不能被限定为输入迭代器。"@康拉德·鲁道夫:它不是
int,int
,而是
T,T
,其中
T
是一种积分类型,至少是C++03中所述的形式。@Eric Postpuschil:最初是这样,因为我误读了问题的一部分。现在有什么是直接相关的。我最初对usin有同样的想法g
是一个整数,但是意识到只为某些数据类型专门启用模板可能更好。我制作的示例将其限制为迭代器为
T
,具体取决于构造函数的具体操作,这可能是需要的(将可能的运行时错误转换为编译时错误)或限制性太强(在这种情况下,使用
迭代器\u traits
的其他方法似乎是合适的