Function template overload
拿Boost.Serialization當範例
1 | namespace boost::serialization { |
Pros:
- 就像膠水,將黏貼部分獨立成單一Unit,需要的時候再引入即可
Cons:
- 跟前個方式依樣,需要打開library的namespace
- 跟前一個方式依樣,存在Name Collisions的可能
Friend member function
又是Boost.Serialization
1 |
|
優缺點正好跟上面相反
Pros:
- 不需要打開library的namespace
- 不會造成Name Collisions
Cons:
- Tightly coupled with structure
當我們如果不需要serialization功能時,透過上面的方式,我們只需要不include implemtation unit即可,不過這方法就不行了
另外一點,這方式引入了boost::serialization的依賴,不管我們需不需要,都必須承受這副作用
ARGUMENT-DEPENDENT LOOKUP
C++最難理解的特性之一
1 | namespace { |
Worng usage example of ADL (std::swap)
What’s wrong with swap
看看以下的程式馬
1 | namespace A { |
- swap(a, b) // invokes ADL because call name is unqualified
- std::swap(a, b) // does not invoke ADL because call name is qualified
如果我們把swap
改成std::stap
,自訂億的swap就毫無作用了
正確的做法應該是
1 | namespace B { |
Correct usage example of ADL (std::swap)
- Create a callable function object which does the two-step with an internal detail namespace’s swap.這做法在Reference中的文章有特別說明,被稱作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21namespace nonstd {
namespace detail {
template <typename T>
void swap(T&, T&) { printf("nonstd::swap\n"); }
struct swap_func {
template <typename T>
void operator()(T &a, T&b) const noexcept {
swap(a, b);
}
};
}
inline constexpr const auto swap = detail::swap_func{};
}
namespace B {
template <typename T>
void test(T& a, T&b)
{
nonstd::swap(a, b);
}
}Customization Point Object
亦或是niebloid
(以作者的名稱命名的單字)
Friend or not?
假設我們把 namespace A中的swap從free_function變成friend function
1 | struct two_things { |
兩者是等價的,不過
- friend function 可以存取 structure的private field,free function不能
- friend function只能被ADL找到
Downgrade to C++11
inline variable是C++17才有的玩意 在有些時候用不了新標準的情況之下 有必要找個方法向下相容
1 | namespace nonstd { |