Template type deduction in functions

Share the Article

When we call a template function, and provide the template arguments in angular brackets “< >”, then we are instantiating it by explicitly specifying template type. However, it is possible to instantiate the templates without specifying template type. In such case, the C++ compiler can itself performs template type deduction by looking at the argument list.

template<typename T> void funda(T x) //template function, T is parameter { } int main() { funda<double>(2.1); //explicit <double> specification funda(4); //type deduction to int return 0; }

Type deduction scenarios

There are mainly 3 scenarios where the compiler applies the rules of template type deduction.

These scenarios are – when the Template Parameter T is:

  1. Not a reference type, but, a parameter-by-value (T)
  2. A reference type (T&)
  3. a universal reference type (T&&)

1. Template Parameter is not a reference (pass-by-value)

template<typename T> void funda(T x);

In such case, whatever the calling code provides, the compiler creates a new copy. This means, if the calling code provides, a reference variable, then compiler shall create a new copy of that variable. Therefore, the template parameter T will no longer be the reference variable.

Similarly, if the calling code provides, a const variable, then also T shall be a copy and it shall not be const.

The following example shows that in multiple scenarios, both the const-ness and reference-ness is not considered in deciding the template parameter type T.

#include <iostream> //main header using namespace std;//for namespace template<typename T> void funda(T x) //Template parameter T is pass-by-value { if(std::is_const_v<typename remove_reference<T>::type>) cout << "const "; if(typeid(x) == typeid(int)) cout << "int"; if(std::is_reference<decltype(x)>( )) if(std::is_lvalue_reference<decltype(x)>( )) cout << "&"; else cout << "&&"; cout << endl; } int main() { int x; funda(x); //T becomes int funda(4); //T becomes int int &y = x; int &&z = 3; funda(y); //T becomes int, & ignored funda(z); //T becomes int, && ignored const int m = 4; funda(m); //T becomes int, const ignored const int &n = m; funda(n); //T becomes int, const and & ignored return 0; }

Output

example output of code using template type deduction with function parameter as pass by value

2. Template parameter is a reference type

template<typename T> void funda(T& x);

In such case, the type of parameter T is deducted as exact type of argument variable sent by calling code. However, if such variable is already a reference variable, then the compiler simply ignores the reference-part to deduce type. But ultimately, due to “&” in parameter, the T finally becomes an L-value reference. In current case, L-value-ness of T causes one limitation that this function can not accept an R-value argument. However, this limitation shall go away if the signature is having “const” keyword.

template<typename T> void funda(const T& x); //accepts R-value also

Please note that in the following code, the “const” aruments deduces T to become “const”.

#include <iostream> //main header using namespace std;//for namespace template<typename T> void funda(T& x) { if(std::is_const_v<typename remove_reference<T>::type>) cout << "const "; if(typeid(x) == typeid(int)) cout << "int"; if(std::is_reference<decltype(x)>( )) if(std::is_lvalue_reference<decltype(x)>( )) cout << "&"; else cout << "&&"; cout << endl; } int main() { int x; funda(x); //T shall become int& // funda(4); //error as T is always L-value int &y = x; int &&z = 3; funda(y); //T shall become int& funda(z); //T shall become int& const int m = 4; funda(m); //T shall become "const int&" const int &n = m; funda(n); //T shall become "const inst&" return 0; }

Output

example output of code using template type deduction with function parameter as pass by reference

3. Template parameter is universal reference

template<typename T> void funda(T&& x);

In this case, the behavior shall be almost same as in case 2 (above). Therefore, T shall always become a reference type. The only difference here is that due to the specification of T as universal reference, the function now accepts both R-value and L-value arguments. Due to reference collapsing rules, if the calling code sends an R-value argument, then T deduces to become R-value reference and with L-value it becomes an L-value reference.

#include <iostream> //main header using namespace std;//for namespace template<typename T> void funda(T&& x) { if(std::is_const_v<typename remove_reference<T>::type>) cout << "const "; if(typeid(x) == typeid(int)) cout << "Type = int"; if(std::is_reference<decltype(x)>( )) if(std::is_lvalue_reference<decltype(x)>( )) cout << "&"; else cout << "&&"; cout << endl; } int main() { int x; funda(x); //T shall become int& funda(4); //T shall become int&& int &y = x; int &&z = 3; funda(y); //T shall become int& funda(z); //T shall become int& const int m = 4; funda(m); //T shall become const int& const int &n = m; funda(n); //T shall become const int& return 0; }

Output

example output of code using template type deduction with function parameter as universal reference

Passing an array to template function

Passing an array to function is a very special case. This is because in some cases, the array variable type can decay into pointer type. The pointer shall point to first element of the array. However, in case of pointers, 2 cases arise

  1. Template parameter T is pass-by-value
  2. Template parameter T is pass-by-reference

In former case, the array shall decay into respective pointer, but in latter case, it retains the array type.

Pass-by-value

#include <iostream> //main header using namespace std;//for namespace template<typename T> void funda(T x) { if(typeid(x) == typeid(int)) cout << "Type = int"; if(typeid(x) == typeid(int[4])) cout << "Type = int[4]"; if(typeid(x) == typeid(int*)) cout << "Type = int*"; if(std::is_reference<decltype(x)>( )) if(std::is_lvalue_reference<decltype(x)>( )) cout << "&"; else cout << "&&"; cout << endl; } int main() { int a1[4] = {1, 2, 3, 4}; funda(a1); return 0; }

Output

output of code which is passing an array to a function template, and array getting decayed to pointer

Pass-by-reference

#include <iostream> //main header using namespace std;//for namespace template<typename T> void funda(T& x) { if(typeid(x) == typeid(int)) cout << "Type = int"; if(typeid(x) == typeid(int[4])) cout << "Type = int[4]"; if(typeid(x) == typeid(int*)) cout << "Type = int*"; if(std::is_reference<decltype(x)>( )) if(std::is_lvalue_reference<decltype(x)>( )) cout << "&"; else cout << "&&"; cout << endl; } int main() { int a1[4] = {1, 2, 3, 4}; funda(a1); return 0; }

Output

output of code passing an array to function template

Getting size of an array using templates type deduction

As in above illustration, an array argument retains the actual array type. Therefore, one application is that we can create a sizeof function. In this case, we may break-down the parameter T further into element-type and array-size components.

template<typename T, std::size_t N> void sizeof_funda(T (&x)[N] )

The following program, prints 3 things,

  1. The overall type of x (which is an array)
  2. The type T (which becomes an int)
  3. Size of the overall array
#include <iostream> //main header using namespace std;//for namespace template<typename T, std::size_t N> void sizeof_funda(T (&x)[N] ) { //Print final type of parameter "x" if(typeid(x) == typeid(int)) cout << "Type(x) = int"; if(typeid(x) == typeid(int[4])) cout << "Type(x) = int[4]"; if(typeid(x) == typeid(int[5])) cout << "Type(x) = int[5]"; if(typeid(x) == typeid(int*)) cout << "Type(x) = int*"; if(std::is_reference<decltype(x)>( )) if(std::is_lvalue_reference<decltype(x)>( )) cout << "&"; else cout << "&&"; cout << ", "; //Printing type of parameter type T if(typeid(T) == typeid(int)) cout << "Type(T) = int"; if(typeid(T) == typeid(int[4])) cout << "Type(T) = int[4]"; if(typeid(T) == typeid(int[5])) cout << "Type(T) = int[5]"; if(typeid(T) == typeid(int*)) cout << "Type(T) = int*"; cout << ", Size of Array = " << N; cout << endl; } int main() { int a1[4] = {1, 2, 3, 4}; sizeof_funda(a1); int a2[5] = {1, 2, 3, 4, 5}; sizeof_funda(a2); return 0; }

Output

example code which implement sizeof method for an array of any type

Main Funda: C++ can deduce the template type from function arguments. There is no need to explicitly provide such type.

Related Topics:

Class Template Argument Deduction in C++17
What is a Tuple, a Pairs and a Tie in C++
C++ Multithreading: Understanding Threads
What is Copy Elision, RVO & NRVO?
Lambda in C++11
Lambda in C++17
What are the drawbacks of using enum ?
Which member functions are generated by compiler in class?
How to stop compiler from generating special member functions?
Compiler Generated Destructor is always non-virtual
How to make a class object un-copyable?
Why virtual functions should not be called in constructor & destructor ?
How std::forward( ) works?
Rule of Three
How std::move() function works?
What is reference collapsing?
How delete keyword can be used to filter polymorphism
emplace_back vs push_back

Share the Article

4,531 thoughts on “Template type deduction in functions

  1. Most householders’ insurance, in the meantime, cowl solely owner-occupied properties and never legal responsibility or damages related to tenants.

  2. Since your Gua Sha tool is made of semi-precious stones it is fragile. Dropping it can damage the crystals in your face tool, thus altering results. Handling your Gua Sha with extreme care is very important. You can store your tool in a dry place and somewhere it will not fall. You can even store it in your refrigerator (or a make-up fridge) for an added cooling effect. Gua sha massage involves scraping your skin with a massaging tool. This can be performed on your body or face. The massage includes a variety of long and short downward strokes to increase blood circulation. Before using the massage tool, you should apply some sort of massage oil for easy traction. What to do before Gua Sha? First on my list of the different types of Gua Sha tools, it’s Rose Quartz. This is one of the most popular gua sha stones out there. Said to be inherently calming and perfect for use on sensitive skin, Rose Quartz the perfect gua sha stone for those with skin complications, or reactive skin. So, if you’re suffering with rosacea and acne, it’s well worth adding a Rose Quartz gua sha to your basket. https://louisvqeu764209.blue-blogs.com/18571885/loreal-match-nude Here are the Top 10 Best Drugstore Primers for fine lines and wrinkles! uneven tone, dehydrated skin, blemishes, lines & wrinkles Our Makeup Brands Get your hands on the perfect canvas with a primer that covers all areas. Lock down your look with the Avant Pro Perfecting Collagen Touche Eclat Primer and make the most of your foundation. Containing the all-important skin care ingredient, collagen, this mattifying primer helps to improve the appearance of wrinkles and fine lines for a naturally youthful complexion on demand. You can receive 50 rewards points by sharing your honest opinion of StriVectin Line BlurFector Instant Wrinkle Blurring Primer. Silicone-based primers are the best to use for aging skin because of its smoothing effect. Each formula has a milky-smooth feel that leaves your faces feeling like silk once it’s applied. “If you think of the wrinkle as a small valley, the silicone fills that valley, creating a smoother surface for you to apply your foundation,” says Caitlin Picou, a makeup artist and owner of the cosmetic brand Kismet. These types of primers are also excellent options for those with oily skin as some contain ingredients that regulate oil production and help extend the wearing time of your makeup.

  3. Worldwide delivery United States USA, Italy, United Kingdom, Germany, Australia, Spain, France, Netherlands, Ireland, Switzerland, Japan, Denmark, Sweden, Austria, Norway, New Zealand, Greece, Belgium 45129 zpack for sale IVF is incredibly taxing, emotional, and intense, but I don t think I d be pregnant right now without it

  4. Pingback: 2abetted
  5. Capitual states that “services provided to international exchanges are up and running, so the information that it had suspended operations to Binance is inappropriate”. The company implies that the decision of suspending its services — that are still available — was Binance’s. There is an active security incident on Solana. Many (7000+ and counting) wallets are drained of SOL & USDC. Don’t know root cause yet. Maybe permissions granted to apps. For remediation, send the funds to a cold wallet or CEX like @Binance. t.co nQrBXAgCbf An entire exchange in a single API. Offer your users access to the crypto world Eu tenho 150 mil dessa moeda ganhei muitos essa semana transfiro para Gate Os irmãos começaram a comprar bitcoin em 2012, quando a criptomoeda valia pouco mais de centavos de dólar. Desde então, os gêmeos têm diversificado seu portfólio de cripto.  https://papa-wiki.win/index.php?title=Usd_to_bitcoin Melhores sites para analisar Criptomoedas: Coingolive é um site brasileiro que permite acompanhar o crescimento, ou a queda, de uma moeda digital no período de até um ano. Os usuários podem usar filtros para avaliar, e é uma ótima opção para comparar criptomoedas através de gráficos. Desde 2020 o Banco Central (BC) do Brasil vem estudando a emissão do real digital — as moedas digitais reguladas por bancos centrais são chamadas de CBDC (Central Bank Digital Currency ou, em português, Moeda Digital de Banco Central) —, mas ainda não há prazo para o seu lançamento. Segundo o BC, as CBDCs teriam potencial para melhorar a eficiência do mercado de pagamentos de varejo e promover a competição e a inclusão financeira da população ainda inadequadamente atendida por serviços bancários.

  6. Gypsy slot is a 5 reel, overview of btc gambling websites its drawn some massive crowds to various sports facilities and casinos that are licensed to operate sportsbooks. In this all-inclusive review, Haldemans continued comments in the press started to worry the guilty parties. As for slots volatility, the player needs to understand the rules. Overall there is little legislation preventing Bitcoin casino gambling, especially at reputable sites which follow laws for each US states. All the Bitcoin casinos we review at InsideBitcoins are in full compliance with the law and have provably fair, independently audited RNGs. Even if you are a little new to the game, it is never too late to get involved with Bitcoin gambling. Especially since the world’s first and foremost cryptocurrency has – and continues to – challenge the way we view alternative ways of spending and trading. Very few industries have been more affected by the radical changes Bitcoin has brought than online gambling. There is little doubt that betting with Bitcoin has given more power back to us, the players. It has also provided betting enthusiasts and casino cats with an even greater level of variety than we have ever had. https://www.bahrulaloom.com/community/profile/felixuvd0901397/ In October 2011, several months after Barden’s death, his estate sold Fitzgeralds to brothers Derek and Greg Stevens, majority owners of the Golden Gate casino. Derek took a 78% ownership share, with 22% for Greg. In February 2017, The D added an exterior video wall promoted as the “World’s Largest Keno Board”, displaying a live feed of keno numbers as they’re drawn inside the casino. In late 2013, the D became the first casino in the world to accept bitcoin for hotel rooms, restaurants, and gift shop items. Additionally, a bitcoin ATM was installed next to the gaming floor where customers can buy and sell bitcoin instantly for cash. More states are expected to approve this form of gambling during the next legislative session; however, if the disappointing results from Tunica are anything to go by, it is understandable why officials are reluctant to make any hasty decisions when it comes to legalized sports betting.