The compiler can often infer a template type from the argument passed to a function.

Template Type Deduction

template_type_deduction.cpp
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string typeName(T value) {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "string";
    } else {
        return "other";
    }
}

int main() {
    int attempts = ;
    std::string word = ;

    std::cout << "attemptType=" << typeName(attempts) << std::endl;
    std::cout << "wordType=" << typeName(word) << std::endl;
    std::cout << "word=" << word << std::endl;
    return 0;
}
type deduction When a call passes an `int`, `std::string`, or another value, the compiler can choose the matching `T`.