检查嵌套的模板化类
Checking for a nested, templated class
我正在尝试构建一个检查嵌套模板类是否存在的trait。这是我检查类O
是否具有模板参数T
的嵌套类inner
的方法:
template <typename O, typename T> struct has_inner {
static const bool value = std::is_class<typename O::template inner<T> >::value;
};
但是,这不能正常工作。给定两个示例类dummy
和ok
struct dummy {};
struct ok {
template <typename T>
struct inner {
};
};
检查ok
std::cout << std::boolalpha << has_inner<ok, float>::value << std::endl;
可以工作,而检查dummy
std::cout << std::boolalpha << has_inner<dummy, int>::value << std::endl;
在clang 3.2上编译失败,报错
error: 'inner' following the 'template' keyword does not refer to a template
static const bool value = std::is_class<typename O::template inner<T> >::value;
^~~~~
note: in instantiation of template class 'has_inner<dummy, int>' requested here
std::cout << std::boolalpha << has_inner<dummy, int>::value << std::endl;
似乎编译器试图在将模板表达式传递给std::is_class
之前实际形成模板表达式。因此,我看到了两个解决方案:
- 告诉编译器延迟模板展开,或者
- 使用完全不同的方法。
但是,我也不知道怎么表演,有人能帮我吗?
问题
您通常使用并依赖于SFINAE来实现这样的特性,而您的实现并没有利用这些特性。
如前所述,编译器将尝试实例化typename O::template inner<T>
,无论是否可能;如果不可能,编译器会在你面前抛出一个错误诊断。
你需要做的是一个条件检查,看看T
是否真的有一个模板类,如果没有,就不实例化它。
解决方案- SFINAE救援!
实现可能像下面的代码片段一样,后面会有解释。
namespace impl {
template<class T, class... Args>
struct has_inner {
template<class U, typename = typename U::template inner<Args...>> // (A)
static std::true_type test (int);
template<class U>
static std::false_type test (...); // (B)
using result_type = decltype (test<T> (0)); // (C)
};
}
template<class... Ts>
using has_inner = typename impl::has_inner<Ts...>::result_type;
注意:通过使用
decltype(test<T>(0))
,我们将有std::true_type或std::false_type,它们都是处理类型特征的结果时的标准行为。
SFINAE规则规定,如果函数模板在实例化时产生无效的函数声明,就好像这个函数不存在一样,编译器将尝试搜索另一个匹配的函数,而不是放弃。
这是在(C)发生的事情,我们尝试调用(A),但如果失败(即。如果在template<class U, typename ...>
中出现无效表达式yield,我们将最终调用(B)。
(B)不如(a)的成功实例化匹配,但是如果(a)不能实例化…
你需要使用一个trait类和SFINAE,就像这样:
template<class A, typename B>
struct has_inner
{
private:
template<class T, typename U>
static std::true_type has(typename T::template inner<U>*);
template<class, typename>
static std::false_type has(...);
public:
static constexpr auto value = decltype(has<A, B>(nullptr))::value;
};
现在你可以使用正确的结果:
static_assert(has_inner<ok, float>::value, "ok does not have inner"); // OK
static_assert(has_inner<dummy, float>::value, "dummy does not have inner"); // ERROR
相关文章:
- 嵌套在类中时无法设置成员数据
- 无法访问嵌套类.类的使用无效
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 在C++中搜索嵌套多映射值
- 在C++中将矢量转换为嵌套地图
- C++嵌套if语句,基本货币交换
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 实现编译检查以避免C++嵌套范围
- 如何用CUDA推力去除嵌套环以进行全对距离检查
- c++检查模板参数的嵌套typedef以获取其标量基类型
- 如何使用嵌套的 if 语句检查字符数组
- 在嵌套循环/循环不变量中检查一次
- 检查嵌套混合中每个类的类型特征
- 如何在C++11中检查类是否指定了嵌套类定义或typedef
- 检查嵌套的模板化类
- Openmp:检查是否嵌套并行
- 使用增强 hana 检查特定的嵌套类型/标记
- 嵌套if -用c++进行嵌套if检查