Ny kurs om C++ templates
Det går knappast att skriva ett (icke-trivialt = seriöst) program i C++ utan att använda sig av färdiga templates. Huvuddelen av standardbiblioteket i C++ bygger på templates, såsom STL algorithms, iterators och containers. Emellertid, anses också templates vara komplicerat, framförallt att skriva egna funktioner eller klasser med hjälp av templates. Och för all del, helt trivialt är det ju inte.
Den här kursen lär dig allt du behöver veta för att inte längre tveka att skriva egna templates. Efter kursen kan du designa implementera egna function och class templates till hjälp för dina kolleger och den organisation du jobbar för.
Här är en sammanställning i punktform av kursen innehåller:
- Function templates
- Class templates
- Variable templates
- Variadic templated
- Fold expressions
- Non-type template parameters
- Template template parameters
- Perfect forwarding
- Template instantiation vs. specialization
- Argument deduction
- SFINAE
- Type traits
- C++20 concepts
Låt oss kika på ett litet exempel, som går ut på att fundera över hur skulle en funktion se ut som kan ta emot värden av stor mängd olika datatyper? Vi kan tänka oss en generell print()
funktion.
auto vec = std::vector<int>{1,2,3,4,5};
print(vec);
auto set = std::unordered_set<std::string>{"C++"s, "is"s, "cool"s};
print(set);
auto map = std::map<std::string, unsigned>{
{"one"s, 1}, {"two"s, 2}, {"three"s, 3}, {"four"s, 4},
};
print(map);
auto arr = std::array<int, 10>{1,1,2,3,5,8,13,21,34,55};
print(arr);
auto number1 = 42U;
print(number1);
print(&number1);
auto number2 = 3.141592654;
print(number);
print(&number);
auto const N = 3;
auto dynArr = new int[N];
dynArr[0] = 11; dynArr[1] = 22; dynArr[3] = 33;
print( Span{dynArr, N} );
auto str = "Hi from a C string";
print(str);
auto strCxx = std::string{"Hi from a C++ string"};
print(strCxx);
Ett annat exempel är hur implementerar man en container constructor som realiserar emplacement och perfect forwarding.
struct Account {
Account(std::string accno, long balance, float rate);
//...
};
auto c = MyContainer<Account>{};
c.insert_first("1122-998877"s, 512L, 1.25F);
Ytterligare ett exempel är, hur ska man tolka vad är syftet med följande kodfragment och hur kan man skriva egna type-requirements.
template<typename T, typename = std::void_t<>>
struct is_stl_container : std::false_type {};
template<typename T>
struct is_stl_container<
T,
std::void_t<
typename T::value_type,
typename T::size_type,
typename T::allocator_type,
typename T::iterator,
typename T::const_iterator,
decltype( std::declval<T>().size() ),
decltype( std::declval<T>().begin() ),
decltype( std::declval<T>().end() ),
decltype( std::declval<T>().cbegin() ),
decltype( std::declval<T>().cend() )
>
> : std::true_type {};
static_assert(is_stl_container< std::vector<int> >());
static_assert(is_stl_container< std::map<std::string,unsigned> >());
static_assert(is_stl_container< std::string >());
struct not_a_container {};
static_assert(!is_stl_container< not_a_container >());
static_assert(!is_stl_container< std::array<int,17> >());
Till sist, hur kommer man igång och använder concepts i C++20?
namespace impl {
template<typename Head, typename...>
struct first_of { using type = Head; };
}
template<typename... Args>
using first_of = typename impl::first_of<Args...>::type;
template<typename... Args>
concept Summable = requires(Args... args) {
requires sizeof...(Args) > 1;
(... + args);
{ (... + args) } noexcept;
{ (... + args) } -> std::same_as<first_of<Args...>>;
};
template<typename... Args>
requires Summable<Args...>
auto sum(Args&& ... args) noexcept {
return (... + args);
}
Alla dessa frågeställningar och många fler, besvarar i denna kolossalt matnyttiga kurs för verksamma C++ programmerare.
Kika på kursens beskrivningssida (se nedan) och boka in ett kursdatum!