C++ 如果没有实例化成员模板,是否要评估静态_断言?

C++ 如果没有实例化成员模板,是否要评估静态_断言?,c++,c++14,C++,C++14,我想我明白了一个静态的断言是如何工作的。但当我在g++编译器上尝试这一点时,我开始怀疑: #include <iostream> #include <type_traits> #define ENABLE_IF(...) std::enable_if_t<__VA_ARGS__, int> = 0 template<typename...Ts> struct list{}; template<typename...Ts> stru

我想我明白了一个静态的断言是如何工作的。但当我在g++编译器上尝试这一点时,我开始怀疑:

#include <iostream>
#include <type_traits>

#define ENABLE_IF(...) std::enable_if_t<__VA_ARGS__, int> = 0

template<typename...Ts>
struct list{};

template<typename...Ts>
struct is_one_of;

template<template <typename...> class TT, typename T, typename T1, typename...Ts>
struct is_one_of<T, TT<T1, Ts...>> : is_one_of<T, TT<Ts...>> {};

template<template <typename...> class TT, typename T, typename...Ts>
struct is_one_of<T, TT<T, Ts...>> : std::true_type {};

template<template <typename...> class TT, typename T>
struct is_one_of<T, TT<>> : std::false_type {};


template<typename...Ts>
struct X;

template<typename P, typename T, typename...Ts>
struct X<P, T, Ts...> : X<P, Ts...>
{
  using X<P, Ts...>::fn;

  template<typename R, ENABLE_IF(std::is_same<T, R>::value)>
  constexpr auto fn(R&& x)
  {
    return x;
  }
};

template<template <typename...> class TT, typename...Ts>
struct X<TT<Ts...>>
{
  template<typename R, ENABLE_IF(!is_one_of<R, TT<Ts...>>::value)>
  constexpr auto fn(R&& x)
  {
    static_assert(false, "Type R didn't match");
  }
};


template<typename...Ts>
struct XX : X<list<Ts...>, Ts...> {};


int main() {
    XX<int, float> x;
    std::cout << x.fn(int(3)) << std::endl;
    return 0;
}
现在我认为根本不可能实例化基类型X,因为它从未被调用过。通过这种推理,它不应该导致静态错误

这在g++5.4.0和clang 3.9.1上失败,但在VC++2015上有效

这是一个缺陷还是我遗漏了什么?

编写static\u assertfalse完全是格式错误,因为它与[temp.res]冲突:

如果出现以下情况,程序格式不正确,无需诊断: -如果模板中的语句6.4.1且模板未实例化,则无法为模板或constexpr的子状态生成有效的专门化

您可以将其视为-因为static_assert的常量表达式是不依赖的,编译器可以立即看到它的格式不正确并触发

您可以不为该专门化提供fn的定义,也可以执行以下操作:

template <class T> struct always_false : std::false_type { };
static_assert(always_false<some_dependent_type>::value, "...");
这将使一个有效的专门化假设成为可能,即使没有人应该专门化总是错误的

编写static_assertfalse完全是格式错误的,因为它与[temp.res]相冲突:

如果出现以下情况,程序格式不正确,无需诊断: -如果模板中的语句6.4.1且模板未实例化,则无法为模板或constexpr的子状态生成有效的专门化

您可以将其视为-因为static_assert的常量表达式是不依赖的,编译器可以立即看到它的格式不正确并触发

您可以不为该专门化提供fn的定义,也可以执行以下操作:

template <class T> struct always_false : std::false_type { };
static_assert(always_false<some_dependent_type>::value, "...");
这将使一个有效的专门化假设成为可能,即使没有人应该专门化总是错误的