我写了以下代码:
#include <iostream>
#include <string>
#include <type_traits>
template<typename, typename = void>
struct is_incrementable : std::false_type {};
template<typename T>
struct is_incrementable<T, decltype( ++std::declval<T&>() )> : std::true_type {};
int main()
{
std::cout << is_incrementable<std::string>::value << std::endl;
std::cout << is_incrementable<int>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
当我跑它,我得到0 0.但我期待0 1.
有任何想法吗?
Rak*_*111 21
对于std::string,选择主模板并考虑专业化.但是decltype(++std::declval<T&>())格式不正确,因此不予考虑,并使用主要模板(非专用模板),从而产生0.
如果使用int,它会变得有点复杂.主要模板由编译器一如既往地选择,然后考虑专门化(这是因为专门化总是被认为是更好的匹配).专门化适用<int, int&>于int,但它与非专用模板<int, void>(void默认模板参数)不匹配,因此专业化将被忽略,因为它不匹配.
因此,默认模板参数的类型必须匹配,否则不考虑特化,因为仅当每个模板参数与特化匹配时才进行特化.
只需在末尾附加一个void()以对第二个模板参数进行特化匹配,因为左表达式被丢弃,而类型为void()is void,它与主模板的第二个模板参数匹配.
template<typename T>
struct is_incrementable<T, decltype( ++std::declval<T&>(), void() )> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
在C++ 17中,您可以使用std::void_t它.