无法调用模板构造函数
Template constructor can't be called
我正在实施类似于 std::list 的 class。我在调用错误的构造函数时遇到问题。
这是一个有效的代码片段:
#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 ;
}
因为值 10
和 20
是 int
当然迭代器 ctor 匹配最好。所以:
- 您可以添加显式转换(例如
size_t(10)
或 static_cast<size_t>(10)
以调用正确的转换。
- 为
size_t
创建一个用户定义的文字,因为没有内置文字
鉴于 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 ) ;
我正在实施类似于 std::list 的 class。我在调用错误的构造函数时遇到问题。
这是一个有效的代码片段:
#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 ;
}
因为值 10
和 20
是 int
当然迭代器 ctor 匹配最好。所以:
- 您可以添加显式转换(例如
size_t(10)
或static_cast<size_t>(10)
以调用正确的转换。 - 为
size_t
创建一个用户定义的文字,因为没有内置文字
鉴于 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 ) ;