【发布时间】:2016-08-02 18:11:03
【问题描述】:
下面带有可变参数模板的 SFINAE 代码可以使用 clang 3.7.1、C++14 很好地编译:
#include <array>
#include <iostream>
#include <vector>
#include <cstdint>
enum class Bar : uint8_t {
ay, bee, see
};
struct S {
static void foo() {}
// std::begin(h) is defined for h of type H
template<typename H, typename... T>
static typename std::enable_if<std::is_pointer<decltype(std::begin(std::declval<H>()))*>::value>::type
foo(const H&, T&&... t)
{ std::cout << "container\n"; foo(std::forward<T>(t)...); }
// H is integral
template<typename H, typename... T>
static typename std::enable_if<std::is_integral<typename std::remove_reference<H>::type>::value>::type
foo(const H&, T&&... t)
{ std::cout << "integer\n"; foo(std::forward<T>(t)...); }
// H is an enum with underlying type = uint8_t
/*
template<typename H, typename... T>
static typename std::enable_if<std::is_same<typename std::underlying_type<H>::type,uint8_t>::value>::type
foo(const H&, T&&... t)
{ std::cout << "enum\n"; foo(std::forward<T>(t)...); }
*/
};
int main()
{
S::foo(std::array<int,8>(), 5, 5L, std::vector<int>{}, 5L);
}
我希望基于 H 类型递归调用正确的 foo 重载:
- 如果为
h类型为H定义了std::begin(h),我想要 选择 1 号过载 - 如果
H是“整数类型”,我想要重载号 2。
按原样工作。但是,如果我为 enum 类型添加另一个重载(您可以尝试取消注释第三个重载),那么我得到:
错误:只有枚举类型有底层类型
我同意只有 enums 有一个底层类型,因此为什么不是第三个重载(带有std::underlying_type)让 SFINAE-d 消失?
【问题讨论】:
-
为什么不直接使用
std::enable_if<std::is_enum<H>::value>::type?它compiles fine。您是否只针对enums 的基础类型为uint8_t?在这种情况下,您可以再添加 1 个条件sizeof(H) == sizeof(uint8_t)。即std::is_enum<H>::value && (sizeof(H) == sizeof(uint8_t))。上面的 ideone 示例对此进行了介绍。 -
@iammilind:很好的建议,谢谢
标签: c++ enums variadic-templates sfinae overload-resolution