I wrote some
template<typename ...T>
inline ARRAY<typename std::common_type<T...>::type, sizeof...(T)> make_array_(const T&..._r)
{ return ARRAY<typename std::common_type<T...>::type, sizeof...(T)>(_r...);
}
which creates a symbol
0000000000000361 t namespace::ARRAY_IMPL<std::common_type<double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double>::type, sizeof (double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double), std::is_trivial<std::common_type<double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double>::type>::value> namespace::make_array_<double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double>(double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&)
Why is std::common_type<double, double, double>::type not collapsing? g version is 5.3.0.
#include <type_traits>
template<typename T, std::size_t SIZE>
struct ARRAY
{ template<typename ...T1>
ARRAY(T1&&...)
{
}
};
template<typename ...T>
inline ARRAY<typename std::common_type<T...>::type, sizeof...(T)> make_array_(const T&..._r)
{ return ARRAY<typename std::common_type<T...>::type, sizeof...(T)>(_r...);
}
const auto sA = make_array_(1.0, 2.0, 3.0);
int main(int, char**)
{
}
CodePudding user response:
Two declarations for function templates are only considered to refer to the same function template if their return types are also equivalent, in contrast to functions where the return type is not considered for matching of declarations.
So you can define a function template
template<typename ...T>
ARRAY<double, sizeof...(T)> make_array_(const T&..._r) {
//...
}
in addition to your template and this will not be considered the same template. Specialization of the two templates for the same template argument list are then also separate functions that could behave completely differently, even if the return type and parameter types of the specializations will be the same.
So in order for the linker to be able to tell the two templates apart, the compiler cannot collapse member typedefs in the symbol.
(Note that "equivalent" here is a technical term with a rather complex definition. It is not always immediately obvious whether two constructs are equivalent if they don't follow the same token sequence and other ODR rules, and there is also the concept of "functionally equivalent" under which there are cases that two declarations for which equivalency can't be determined the program is IFNDR (ill-formed, no diagnostic required).)