我有简化版的代码:
#include <experimental/type_traits>
template<class T> using has_data_t = decltype(T::data());
template <class B> constexpr auto get_data() {
return std::experimental::is_detected_v<has_data_t, B>;
}
template <typename Topt> struct opt_base {
static constexpr bool i = get_data<Topt>();
//static constexpr auto j = get_data<Topt>(); // fail to compile
};
struct opt : public opt_base<opt> {
static int data() { return 7;}
};
int main() {
static_assert(std::experimental::is_detected_v<has_data_t, opt>);
}
此代码编译。但是,如果您取消注释注释行,则断言失败。它使用 GCC 7.1 和 Clang 4.0.0 进行了测试。编译参数:-std=c++1z -O3 -Wall。 Demo
最佳答案
在这段代码中:
static constexpr bool i = get_data<Topt>();
static constexpr auto j = get_data<Topt>();
Topt
(即 opt
)尚未完成。所以is_detected_v<has_data_t, opt>
应该是false
.但是当我们到达 main
时, opt
已完成。所以我们期望 is_detected_v<has_data_t, opt>
成为true
.
拥有一个在不同上下文中实例化时会产生不同结果的模板意味着您的程序格式错误,不需要诊断。参见[温度点]:
A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.
添加j
并不重要 - 它只是碰巧翻转了改变编译器选择实例化方式顺序的开关。无论 j
是否存在,程序都是错误的.
关于c++ - 继承和 is_detected_v 提供了一个奇怪的结果 (C++17),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43793824/