【发布时间】:2020-05-28 00:40:15
【问题描述】:
首先,为这个可怕的标题道歉。我正在试验 C++20 is_detected 功能。 is_detected 基本上接受两个模板参数,一个是执行检查的高阶类型,另一个是要检查的类型。我在以下场景中遇到了问题:
#include <stdio.h>
#include <type_traits>
// kind of how std::experimental::is_detected is implemented
template <template <typename> typename Checker, typename T, typename = void>
struct is_detected: std::false_type {};
template <template <typename> typename Checker, typename T>
struct is_detected<Checker, T, std::void_t<Checker<T>>>: std::true_type {};
struct Foo {
template <typename T>
using Checker = decltype(std::declval<T>().foo());
template <typename T>
static constexpr void call(T &t) {
t.foo();
}
};
template <typename T>
using GlobalChecker = decltype(std::declval<T>().foo());
template <typename T>
struct Wrapper {
template <typename U>
using LocalChecker = typename T::template Checker<U>;
// ^^^^^^^^ clang and msvc require template keyword
// gcc doesn't require it
template <typename U>
constexpr void conditional_call(U &u) const noexcept {
if constexpr (
is_detected<
typename T::Checker,// !!! COMPILE ERROR !!!
// works for
// GlobalChecker,
// LocalChecker and
// Foo::Checker, though.
std::decay_t<U>>
::value) {
Foo::call(u);
}
else {
puts("fallback");
}
}
};
int main() {
struct {
void foo() {
puts("heyy!");
}
} t;
Wrapper<Foo> w;
w.conditional_call(t); // heyy! (if foo didn't exist, then fallback)
}
如果我在类范围内使用using LocalChecker = typename T::template Checker<U>; 为Checker 起别名,则它可以工作;但是,我想了解是否有其他方法不使用using。另外,我需要template 这个using 定义吗?因为 Clang 和 GCC 对此意见不一。
【问题讨论】:
标签: c++ templates c++20 template-templates