5

Consider following program:

#include <iostream>
#include <limits>

template<float f>
void fun(){
    std::cout << "val: " << f << "\n";
}

template<>
void fun<std::numeric_limits<float>::signaling_NaN()>(){
    std::cout << "sn\n";
}

int main() {
    static_assert(std::numeric_limits<float>::signaling_NaN()!=std::numeric_limits<float>::signaling_NaN());
    fun<std::numeric_limits<float>::signaling_NaN()>();
    fun<std::numeric_limits<float>::quiet_NaN()>();
}

It prints out:

sn
val: nan

So this makes me think that compiler does bitwise comparison of floats when it comes to template specialization consideration(see static_assert). Is this correct?

I tried reading the 13.4.3 Template non-type arguments but it does not seem specified there, but I have really hard time reading the standard so I may be missing something obvious.

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • It appears you're mostly correct [for floats it only cares if the representation is identical](https://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter) (scroll down to Template argument equivalence) – Mgetz Oct 12 '21 at 14:09
  • 1
    @Mgetz: [template_parameters#Template_argument_equivalence](https://en.cppreference.com/w/cpp/language/template_parameters#Template_argument_equivalence) to not scroll manually :) – Jarod42 Oct 12 '21 at 14:17
  • 1
    Notice that clang rejects the code. [Demo](https://godbolt.org/z/qbx41GovK). – Jarod42 Oct 12 '21 at 14:22
  • 1
    It’s not really a duplicate, since it’s about support for the feature, but [the history](https://stackoverflow.com/q/63694879/8586227) does explain/motivate the rule. – Davis Herring Oct 12 '21 at 14:23
  • @Jarod42 I think clang has not fully implemented the feature, I got unimplemented error when experimenting, can not reproduce it now. – NoSenseEtAl Oct 12 '21 at 14:33
  • @Jarod42 "or they are of floating-point type and their values are identical" now we get to discuss what did the poet mean when he said "identical" – NoSenseEtAl Oct 12 '21 at 14:34
  • 2
    standard ([temp#type-2](https://eel.is/c++draft/temp#type-2)) doesn't give more info. Moreover, is *"values are the same"* (integral case) and *"values are identical"* (floating point) has same/identical meaning? – Jarod42 Oct 12 '21 at 14:53
  • I prefer the consistent result from clang. – Jarod42 Oct 12 '21 at 14:56
  • @DavisHerring your answer talks about floats in a way that does not fit my current example, maybe I misread it, but I understood that what you say is that different representations are counted as same, e.g 0.0 and -0.0 https://godbolt.org/z/cav3TeTTK – NoSenseEtAl Oct 12 '21 at 15:12
  • @NoSenseEtAl: No, I said representations are *compared* instead of comparing values (with `==`). – Davis Herring Oct 12 '21 at 15:15
  • @DavisHerring ok, then I misunderstood : "he semantics that would result from such a trick would be that every representation of a float would be a different template argument, despite the fact that -0.0==0.0 and (given float nan=std::numeric_limits::quiet_NaN();) nan!=nan. It was therefore proposed that floating-point values be allowed directly as template arguments, with those semantics, to avoid encouraging widespread adoption of such a hacky workaround." – NoSenseEtAl Oct 12 '21 at 15:25

0 Answers0