我经常为类创建
this_type
typedef 以缩短成员函数签名。
然而,我在使用std::enable_if_t
时遇到了这个奇怪的情况。
#include <iostream>
#include <string>
#include <type_traits>
template <class T, class Enable = void>
struct foo;
template <class T>
struct foo <T, std::enable_if_t<std::is_arithmetic_v<T>>>
{
T data {};
//typedef foo<T, void> this_type; // <-- can't do this
//typedef foo<T, std::enable_if_t<true>> this_type; // <- can't do this either
typedef foo<T, std::enable_if_t<std::is_arithmetic_v<T>>> this_type; // have to do this
foo () = default;
explicit foo(T i): data(i) {}
foo (this_type const &) = default;
};
你不能在
this_type
的定义中使用完全等价的类型——当然,错误是 foo (this_type const &)
不能被默认,因为 this_type
与实际的类不匹配。
但它们都是同一类型:
int main(void)
{
std::boolalpha(std::cout);
std::cout << "enable_if_t: " << typeid(std::enable_if_t<std::is_arithmetic_v<int>>).name() << '\n';
foo<int> myfoo{1};
std::cout << "Same: " << std::is_same_v<decltype(myfoo), foo<int, void>> << '\n';
std::cout << typeid(decltype(myfoo)).name() << '\n';
std::cout << typeid(foo<int, void>).name() << '\n';
std::cout << typeid(foo<int>::this_type).name() << '\n';
foo<int> myfoo2(myfoo);
return 0;
}
海湾合作委员会输出:
enable_if_t: v
Same: true
3fooIivE
3fooIivE
3fooIivE
一旦专业化成功,编译器就应该知道这一点:
std::enable_if_t
的结果立即被类型替换,在本例中为void
。示例输出证实了这一点。
我认为这可能与旧的 C++ 标准在名称空间范围内相同类型的 typedef 之间产生的问题有关,但这不是原因,因为否则
typedef foo<T, std::enable_if_t<true>> this_type
会起作用。
是什么阻止了较短的类型别名被识别?
您可以简单地将其定义为
typedef foo this_type;
// or
using this_type = foo;
在这种情况下,foo
是一个注入类名,它指的是foo
的当前专业化。
无需显式提供模板参数。