没有 void_t 的 SFINAE(可能是模板专业化问题)
SFINAE without void_t (maybe a template specialization question)
对不起标题,我不确定我问题的类别。
我正在尝试使用 SFINAE 进行 is_incrementable。这工作正常,但是当我尝试更深入地理解它时,当我删除 void_t 时,代码片段无法按预期工作。
原代码:
#include <iostream>
template< typename, typename = void >
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,
std::void_t<decltype( ++std::declval<T&>() )>
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 1
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
i) is_incrementable<int>::value
评估为 is_incrementable<int, void>::value
,这是原始模板 class 和专业化。在这种情况下,编译器选择专用版本,因此值等于 1。
对于字符串版本,专业化失败,SFINAE 启动,所以我们只有基本模板。 (值等于 0)
ii) 当我更改代码并删除 void_t
template< typename, typename = void >
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,
decltype( ++std::declval<T&>() ) // void_t is removed
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 0
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
0 并打印 0。
is_incrementable<int>::value
表示is_incrementable<int, void>::value
,特化为
is_incrementable<int, int>::value
(我认为),所以我们使用基本模板。对于字符串,专业化无论如何都会失败。
我的问题:
三)
有趣的部分。
如果现在我将第一行更改为使用 int 作为默认类型
#include <iostream>
template< typename, typename = int > // !!! int is used now
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,
decltype( ++std::declval<T&>() ) // void_t is removed
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 0
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
然后再次打印 0 和 0。
为什么?
is_incrementable<int>::value
表示(我认为)is_incrementable<int, int>::value
和
decltype( ++std::declval<T&>() )
也应该是 int。
所以我认为编译器应该使用专门的版本。 (应该打印 1)
如果我删除
decltype( ++std::declval<T&>() )
并写入 int
然后打印 1 和 1(这是预期的打印输出)。
有人可以向我解释一下 iii) 中发生了什么吗。
当T
是int
时,decltype( ++std::declval<T&>() )
是int &
,而不是int
。因此,要获得您期望的输出,您可以更改此设置:
template< typename, typename = int >
struct is_incrementable : std::false_type { };
对此:
template< typename, typename = int & >
struct is_incrementable : std::false_type { };
或者改变这个:
template< typename T >
struct is_incrementable<T,
decltype( ++std::declval<T&>() )
> : std::true_type { };
对此:
template< typename T >
struct is_incrementable<T,
std::remove_reference_t<
decltype( ++std::declval<T&>() )
>
> : std::true_type { };
对不起标题,我不确定我问题的类别。 我正在尝试使用 SFINAE 进行 is_incrementable。这工作正常,但是当我尝试更深入地理解它时,当我删除 void_t 时,代码片段无法按预期工作。
原代码:
#include <iostream>
template< typename, typename = void >
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,
std::void_t<decltype( ++std::declval<T&>() )>
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 1
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
i) is_incrementable<int>::value
评估为 is_incrementable<int, void>::value
,这是原始模板 class 和专业化。在这种情况下,编译器选择专用版本,因此值等于 1。
对于字符串版本,专业化失败,SFINAE 启动,所以我们只有基本模板。 (值等于 0)
ii) 当我更改代码并删除 void_t
template< typename, typename = void >
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,
decltype( ++std::declval<T&>() ) // void_t is removed
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 0
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
0 并打印 0。
is_incrementable<int>::value
表示is_incrementable<int, void>::value
,特化为
is_incrementable<int, int>::value
(我认为),所以我们使用基本模板。对于字符串,专业化无论如何都会失败。
我的问题: 三) 有趣的部分。 如果现在我将第一行更改为使用 int 作为默认类型
#include <iostream>
template< typename, typename = int > // !!! int is used now
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,
decltype( ++std::declval<T&>() ) // void_t is removed
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 0
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
然后再次打印 0 和 0。
为什么?
is_incrementable<int>::value
表示(我认为)is_incrementable<int, int>::value
和
decltype( ++std::declval<T&>() )
也应该是 int。
所以我认为编译器应该使用专门的版本。 (应该打印 1)
如果我删除
decltype( ++std::declval<T&>() )
并写入 int
然后打印 1 和 1(这是预期的打印输出)。
有人可以向我解释一下 iii) 中发生了什么吗。
当T
是int
时,decltype( ++std::declval<T&>() )
是int &
,而不是int
。因此,要获得您期望的输出,您可以更改此设置:
template< typename, typename = int >
struct is_incrementable : std::false_type { };
对此:
template< typename, typename = int & >
struct is_incrementable : std::false_type { };
或者改变这个:
template< typename T >
struct is_incrementable<T,
decltype( ++std::declval<T&>() )
> : std::true_type { };
对此:
template< typename T >
struct is_incrementable<T,
std::remove_reference_t<
decltype( ++std::declval<T&>() )
>
> : std::true_type { };