C++ Logo

std-proposals

Advanced search

[std-proposals] Function overload set type information loss

From: organicoman <organicoman_at_[hidden]>
Date: Tue, 30 Jul 2024 04:01:32 +0400
Hello Gents,Let:O(f) be the Set of 'function overloads' of the function named "f".Let:"Ret" be the return type of function "f".The elements of O(f) can have 2 forms:1-> Ret f ( Vargs ) 2-> Ret f <Ts...> ( Fargs ) Where:1-> "Vargs" is a variadic list of arguments types, participating or not in template type arguments deduction if "f" is a template. e.g: template<typename T, typename V>void f(T, V, double, int)Vargs = {T, V, double, int}2-> "Fargs" is a fixed list of arguments types, not related to any template type parameter. e.g: template <typename T, typename V>void f(double, int)Fargs= {double, int} // T,V are not in the list."Ts" is just a variadic list of template parameters types.The type of any function of the 1st form is:decltype (f) = Ret(*)(Vargs), which keeps information about the function's type template parameters participating in the function argument's list.But the type of the 2nd form is:decltype (f) = Ret(*)(Fargs);No mater what the template parameters are, the type of the 2nd form always decays to:Ret(*)(Fargs)And always lose any type information about the function's type template parametersYet, when we want to get the address of such function, we are obligated to use the template types in the function name. e.g:auto select_f = &f<Ts...>;Otherwise we get overload ambiguity, This is a proof that the template arguments participates in the function type.In my opinion, the compiler should keep the template arguments type information.I know that changing the type of "select_f" in the example above will break a lot of code.But i have a suggestion. If the compiler can keep record of :* an apparent function type ; (the usual one) decltype (&f<Ts...>) = Ret(*)(Fargs)* and an effective function type which is: decltype (&f<Ts...>) = Ret(*)<Ts...>(Fargs) This would fix the problem without breaking any neck.Why is this useful?Take this example:struct Erased{std::any (*m_fun) (void);template<auto Func>constexpr Erased() : m_fun(Func){ }auto operator ()(){ using f_type = effective_decltype (m_fun); // imagin we have a type traits that // extracts template types. using T = extract_1st_template_type<f_type>; return std::any_cast<T>( m_fun(void) );}};template <typename Ret>std::any foo(){ return Ret{}; }int main(){  std::vector<Erased> vec;  vec.push_back(Erased<&foo<int>>{});  vec.push_back(Erased<&foo<double>>{}); vec.push_back(Erased<&foo<some_type>>{}); for(const auto& elem: vec) DoSomethingBasedOnReturnType(elem());}Using this technique we can store the template type, then recall it back.I guess it will make type erasure more effecient.Any thoughts?RegardsNadirSent from my Galaxy

Received on 2024-07-30 00:01:44