0%

Summary about C++17 Part 2

if constexpr

以往我們可能寫出類似這樣的程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string>
template <typename T>
int func(T) {
return -1;
}
template <>
int func(std::string v)
{
return 12;
}
template <>
int func(int)
{
return 34;
}
int main()
{
return func(std::string("123"));
}

如今我們可以寫成這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <string>
template <typename T>
int func(T) {
if constexpr (std::is_same_v<T, std::string>) {
return 12;
} else if constexpr(std::is_same_v<T, int>) {
return 34;
} else {
return -1;
}
}
int main()
{
return func(std::string("123"));
}

省去了很多的冗於
如果配合variant來使用,程式碼可以寫成這樣

1
2
3
4
5
6
7
8
9
10
11
12
#include <string>
#include <variant>
using unionType = std::variant<std::string, int>;
int main()
{
unionType v = 3;
return std::visit([](const auto &v) {
using T = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<T, int>) return 12;
else return 34;
}, v);
}

Class Deduction guide

在c++17之前,寫了很多這樣子的程式碼

1
2
std::mutex m;
std::lock_guard<std::mutex> lock(m);

為什麼函數可以推導出型別,而類型不行,於是C++17放寬了這條件

1
2
std::lock_guard lock(m);
std::vector v{1, 2, 3};

當然,也是有explicit class deduction guide的,請參考reference

template <auto>

目前看起來沒什麼用的feature
未用c++17前程式碼長這樣

1
2
3
4
5
template <typename T, T v>
struct integral_constant {
static constexpr T value = v;
};
integral_constant<int, 1024>::value;

用了C++17後

1
2
3
4
5
template <auto v>
struct integral_constant {
static constexpr auto value = v;
};
integral_constant<1024>::value;

nested namespace

早該有的東西, 結果拖到這麼後面才加進來

1
2
3
4
5
namespace X {
namespace Y {
struct Foo;
}
}

現在可以寫成

1
2
3
namespace X::Y {
struct Foo;
}

Fold expression

以加法為範例
在c++17之前的寫法

1
2
3
4
5
6
7
8
template<typename T>
T sum(T v) {
return v;
}
template<typename T, typename... Args>
T sum(T first, Args... args) {
return first + sum(args...);
}

把sum寫成兩部分,雖然不是不行,不過總覺得被切割加重學習負擔
用上if constexpr

1
2
3
4
5
6
7
8
template<typename T, typename... Args>
T sum(T first, Args... args) {
if constexpr (sizeof...(Args) == 0) {
return first;
} else {
return first + sum(args...);
}
}

好一點了,用上Fold expression會變成怎樣

1
2
3
4
template<typename ...Args>
auto sum(Args&&... args) {
return (args + ...); // OK
}

if constexpr方法比是更精簡了一點,不過多了一堆語法規則,實在不太划算

Reference

A Tour of C++ 17: If Constexpr
C++17中的deduction guide
C++17 Fold Expressions