4

For example I got some template classes:

template <typename T, typename = void>
struct A {
  void Print() {
    static_assert(false, "fall into unsupported Print function");
  }
};
// an instantiation if T is a unsigned type
template <typename T>
struct A<T, typename std::enable_if_t<std::is_unsigned<T>::value>> {
  void Print() {
    std::cout << "A<int>" << std::endl;
  }
};

but due to the standard:

If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required.

clang will immediately stop compiling and show failures, no matter if the template class gets instantiated or not, which is not what I meant to do.

I tried some other way like add a constexpr bool funtion to return false, but all failed.

So is there's any trick I can make the static_assert trigger only if the template class is instantiated?

JFMR
  • 23,265
  • 4
  • 52
  • 76

1 Answers1

4

If the expression inside static_assert depends on a template parameter, the assertion will be deferred until instantiation. You could, for example, define the following class template, deferred_false:

#include <type_traits> // std::false_type

template<typename>
struct deferred_false: std::false_type {};

Then, use it in the static_assert:

template <typename T, typename = void>
struct A {
  void Print() {
    static_assert(deferred_false<T>::value, "fall into unsupported Print function");
  }
};
JFMR
  • 23,265
  • 4
  • 52
  • 76
  • Although this works in practice, does it not violate the standard still? – Daniel Sep 07 '20 at 13:12
  • @Dani Why? I would say this simply takes advantage of the [*Two-Phase Lookup*](https://stackoverflow.com/q/7767626/8012646) for templates: *lookup for non-dependent names is done in the first phase, whereas lookup for names that depend on a template parameter is done in the second phase* ([in the comment](https://stackoverflow.com/questions/7767626/two-phase-lookup-explanation-needed#comment9456869_7767726)). – JFMR Sep 07 '20 at 13:15
  • @Dani No, it's fine, and the reason is because there *may* be a specialization of `deerred_false` which evaluates to `true_type`. – cigien Sep 07 '20 at 13:28