c++ - 继承和 is_detected_v 提供了一个奇怪的结果 (C++17)

标签 c++ templates c++17

我有简化版的代码:

#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/

相关文章:

python - Django 小部件模板覆盖不会在项目模板目录中搜索。怎么修?

C++ Type Traits if_v(自动类型推导+确保类型相同)

c# - 在 RasDial 之后获取 IP 地址/接口(interface)号

c++ - "expected ' : ', ' , ', ' ; ', ' } ' or ' __attribute__ ' before ' { 结构成员函数中的' token"

c++ - 在将 char 数组复制到字符串期间节省 CPU 周期(提高性能)

c++ - Visual 2010 C++ 中的错误 C2784

c++ - 使用 SFINAE 检查 C++ 中的模板父类

wpf - WPF和Powershell,需要知道如何向控件元素添加样式

c++ - 作为函数参数和返回值的不完整类型

c++ - 使用带索引的包扩展 - 是 UB 吗?