Конструктор шаблона не может быть вызван - PullRequest
2 голосов
/ 14 июня 2019

Я реализую класс, похожий на std :: list. У меня проблемы с вызовом неправильного конструктора.

Вот фрагмент рабочего кода:

#include <iostream>

template <typename T>
class dslist
{
public :
    typedef size_t    size_type ;
public :
    explicit dslist( const size_type count , const T &value ) ;
    template <typename InputIt>
    explicit dslist( InputIt first , InputIt last ) ;
} ;
template <typename T>
dslist<T>::dslist( const size_type count , const T &value )
{
    std::cout << "count, value ctor" << std::endl ;
}
template <typename T>
template <typename InputIt>
dslist<T>::dslist( InputIt first , InputIt last )
{
    std::cout << "Iterator" << std::endl ;
}

int main()
{
    dslist<int> l( 10 , 20 ) ;
    return 0 ;
}

Если я запускаю это, вызывается конструктор итератора. Но на самом деле первый конструктор (count, value) должен быть вызван.

Как обеспечить вызов первого конструктора в этом случае?

Изменить, чтобы добавить решение, извлеченное из ответа:

Решение

#include <iostream>
#include <utility>
#include <vector>
#include <type_traits>

template <typename T>
class dslist
{
public :
    typedef size_t    size_type ;
public :
    explicit dslist( const size_type count , const T &value ) ;
    template <typename InputIt, typename = decltype(*std::declval<InputIt>())>
    explicit dslist( InputIt first , InputIt last ) ;
} ;
template <typename T>
dslist<T>::dslist( const size_type count , const T &value )
{
    std::cout << "count, value ctor" << std::endl ;
}
template <typename T>
template <typename InputIt, typename>
dslist<T>::dslist( InputIt first , InputIt last )
{
    std::cout << "Iterator" << std::endl ;
}

int main()
{
    dslist<int> l( 10 , 20 ) ;

    std::vector<int> v( 10 ) ; 
    dslist<int> l1( std::begin( v ) , std::end( v ));
    return 0 ;
}

Ответы [ 2 ]

6 голосов
/ 14 июня 2019

Учитывая dslist<int> l( 10 , 20 ) ;, конструктор шаблона выигрывает в разрешении перегрузки, потому что это точное совпадение. В то время как первый конструктор требует имплицитного преобразования из int (тип 10) в size_t (целочисленный тип без знака).

Вы можете использовать SFINAE , чтобы исключить нежелательные специализации из набора перегрузки. например тип итератора должен поддерживать operator*.

template <typename InputIt, typename = decltype(*std::declval<InputIt>())>
explicit dslist( InputIt first , InputIt last ) ;

ЖИТЬ

0 голосов
/ 14 июня 2019

Так как значения 10 и 20 равны int, конечно, ctor итератора подходит лучше всего. Итак:

  1. Вы можете добавить явные приведения (например, size_t(10) или static_cast<size_t>(10), чтобы вызвать правильное.
  2. Создайте пользовательский литерал для size_t, поскольку для него нет встроенных литералов
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...