VLink 2.0.0
A high-performance communication middleware
载入中...
搜索中...
未找到
uint128.h
浏览该文件的文档.
1/*
2 * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 * Author: Thun Lu <thun.lu@zohomail.cn>
4 * Repo: https://github.com/thun-res/vlink
5 * _ __ __ _ __
6 * | | / / / / (_) ____ / /__
7 * | | / / / / / / / __ \ / //_/
8 * | |/ / / /___ / / / / / / / ,<
9 * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/**
25 * @file uint128.h
26 * @brief Portable 128-bit unsigned integer with full arithmetic, bitwise, and comparison operators.
27 *
28 * @details
29 * @c Uint128 represents a 128-bit unsigned value as two @c uint64_t halves (@c high_ and
30 * @c low_). On platforms that provide @c __uint128_t (GCC/Clang with 64-bit targets),
31 * multiplication is delegated to the compiler's native type for maximum performance. On
32 * other platforms a portable fallback algorithm (@c mul_u128_fallback) is used.
33 *
34 * Supported operations:
35 *
36 * | Category | Operators | Notes |
37 * | ------------- | --------------------------------------------- | ------------------------------ |
38 * | Arithmetic | + - * / % += -= *= /= %= | / and % throw on divisor zero |
39 * | Bitwise | | & ^ ~ << >> |= &= ^= <<= >>= | Shifts clamped to [0, 127] |
40 * | Comparison | == != < > <= >= | Lexicographic (high then low) |
41 * | Increment | ++ -- (prefix and postfix) | 128-bit carry propagated |
42 * | Stream | operator<<(ostream) | Hexadecimal output |
43 *
44 * @par Implicit conversion from integral types
45 * A non-explicit single-argument constructor accepts any integral type @c T:
46 * - If @c T is @c __uint128_t (when available), high and low halves are extracted.
47 * - Otherwise the value is zero-extended into the low 64 bits.
48 *
49 * @par Conversion to __uint128_t
50 * On platforms that support it, an explicit @c operator __uint128_t() is provided for
51 * interoperability with compiler-native 128-bit arithmetic.
52 *
53 * @par std::hash specialisation
54 * A @c std::hash<vlink::Uint128> specialisation is defined at the bottom of this file,
55 * enabling @c Uint128 to be used as a key in @c std::unordered_map / @c std::unordered_set.
56 *
57 * @par Type alias
58 * @code
59 * using uint128_t = Uint128;
60 * @endcode
61 *
62 * @par Example
63 * @code
64 * vlink::Uint128 a(0, UINT64_MAX); // 0xFFFFFFFFFFFFFFFF
65 * vlink::Uint128 b(1, 0); // 0x10000000000000000
66 * vlink::Uint128 c = a + vlink::Uint128(0, 1); // carry propagates to high word
67 * assert(c == b);
68 *
69 * // Hash map usage:
70 * std::unordered_map<vlink::uint128_t, std::string> map;
71 * map[vlink::Uint128(0xDEAD, 0xBEEF)] = "key";
72 * @endcode
73 */
74
75#pragma once
76
77#include <cstdint>
78#include <iostream>
79#include <type_traits>
80#include <utility>
81
82#include "./macros.h"
83
84namespace vlink {
85
86/**
87 * @class Uint128
88 * @brief 128-bit unsigned integer stored as two 64-bit halves with full operator support.
89 *
90 * @details
91 * Stores the value as @c (high_ << 64) | low_. All arithmetic correctly handles
92 * carry/borrow across the 64-bit boundary. Division and modulo are implemented using
93 * a portable binary-long-division algorithm (@c u128_divmod).
94 */
95class Uint128 final {
96 public:
97 /**
98 * @brief Default-constructs a zero-valued @c Uint128.
99 */
100 Uint128() noexcept = default;
101
102 /**
103 * @brief Constructs a @c Uint128 from any integral type @p T (implicit conversion).
104 *
105 * @details
106 * - If @c T is @c __uint128_t (available on GCC/Clang 64-bit), splits into high and low halves.
107 * - Otherwise zero-extends the value into @c low_; @c high_ is set to zero.
108 *
109 * @tparam T Source integral type.
110 * @param v Source value.
111 *
112 * @note This constructor is intentionally non-explicit to allow natural integral literals.
113 */
114 template <typename T>
115 constexpr Uint128(T v) noexcept; // NOLINT(google-explicit-constructor)
116
117 /**
118 * @brief Constructs a @c Uint128 from explicit high and low 64-bit halves.
119 *
120 * @param high Upper 64 bits.
121 * @param low Lower 64 bits.
122 */
123 explicit Uint128(uint64_t high, uint64_t low) noexcept;
124
125#if defined(__SIZEOF_INT128__)
126 /**
127 * @brief Converts to the compiler-native @c __uint128_t type.
128 *
129 * @details
130 * Only available on platforms that provide @c __uint128_t (GCC/Clang, 64-bit targets).
131 * Reconstructed as @c (high_ << 64) | low_.
132 *
133 * @return Native 128-bit value.
134 */
135 explicit operator __uint128_t() const noexcept;
136#endif
137
138 /**
139 * @brief Returns the sum of @c *this and @p other.
140 *
141 * @param other Right-hand operand.
142 * @return New @c Uint128 equal to @c *this + @p other.
143 */
144 Uint128 operator+(const Uint128& other) const noexcept;
145
146 /**
147 * @brief Returns the difference of @c *this and @p other.
148 *
149 * @param other Right-hand operand.
150 * @return New @c Uint128 equal to @c *this - @p other (wraps on underflow).
151 */
152 Uint128 operator-(const Uint128& other) const noexcept;
153
154 /**
155 * @brief Returns the product of @c *this and @p other.
156 *
157 * @details
158 * Uses @c __uint128_t multiplication when available; falls back to
159 * @c mul_u128_fallback otherwise.
160 *
161 * @param other Right-hand operand.
162 * @return New @c Uint128 equal to @c *this * @p other (low 128 bits of true product).
163 */
164 Uint128 operator*(const Uint128& other) const noexcept;
165
166 /**
167 * @brief Returns the quotient of @c *this divided by @p other.
168 *
169 * @param other Divisor.
170 * @return New @c Uint128 equal to @c *this / @p other.
171 *
172 * @throws std::domain_error (or similar) if @p other is zero.
173 */
174 Uint128 operator/(const Uint128& other) const;
175
176 /**
177 * @brief Returns the remainder of @c *this divided by @p other.
178 *
179 * @param other Divisor.
180 * @return New @c Uint128 equal to @c *this % @p other.
181 *
182 * @throws std::domain_error (or similar) if @p other is zero.
183 */
184 Uint128 operator%(const Uint128& other) const;
185
186 /**
187 * @brief Adds @p other to @c *this in-place with carry propagation.
188 *
189 * @param other Right-hand operand.
190 * @return Reference to @c *this.
191 */
192 Uint128& operator+=(const Uint128& other) noexcept;
193
194 /**
195 * @brief Subtracts @p other from @c *this in-place with borrow propagation.
196 *
197 * @param other Right-hand operand.
198 * @return Reference to @c *this.
199 */
200 Uint128& operator-=(const Uint128& other) noexcept;
201
202 /**
203 * @brief Multiplies @c *this by @p other in-place.
204 *
205 * @param other Right-hand operand.
206 * @return Reference to @c *this.
207 */
208 Uint128& operator*=(const Uint128& other) noexcept;
209
210 /**
211 * @brief Divides @c *this by @p other in-place.
212 *
213 * @param other Divisor.
214 * @return Reference to @c *this.
215 *
216 * @throws std::domain_error (or similar) if @p other is zero.
217 */
218 Uint128& operator/=(const Uint128& other);
219
220 /**
221 * @brief Computes @c *this modulo @p other in-place.
222 *
223 * @param other Divisor.
224 * @return Reference to @c *this.
225 *
226 * @throws std::domain_error (or similar) if @p other is zero.
227 */
228 Uint128& operator%=(const Uint128& other);
229
230 /**
231 * @brief Returns the bitwise OR of @c *this and @p other.
232 *
233 * @param other Right-hand operand.
234 * @return New @c Uint128 with each bit set if it is set in either operand.
235 */
236 Uint128 operator|(const Uint128& other) const noexcept;
237
238 /**
239 * @brief Returns the bitwise AND of @c *this and @p other.
240 *
241 * @param other Right-hand operand.
242 * @return New @c Uint128 with each bit set only if set in both operands.
243 */
244 Uint128 operator&(const Uint128& other) const noexcept;
245
246 /**
247 * @brief Returns the bitwise XOR of @c *this and @p other.
248 *
249 * @param other Right-hand operand.
250 * @return New @c Uint128 with each bit set if it differs between operands.
251 */
252 Uint128 operator^(const Uint128& other) const noexcept;
253
254 /**
255 * @brief Returns the bitwise NOT (complement) of @c *this.
256 *
257 * @return New @c Uint128 with all 128 bits inverted.
258 */
259 Uint128 operator~() const noexcept;
260
261 /**
262 * @brief Returns @c *this shifted left by @p shift bits.
263 *
264 * @details
265 * - Shift <= 0: returns @c *this unchanged.
266 * - Shift >= 128: returns zero.
267 * - Shift in [64, 127]: low bits are shifted into the high word.
268 *
269 * @param shift Number of bit positions to shift left.
270 * @return Shifted value.
271 */
272 Uint128 operator<<(int shift) const noexcept;
273
274 /**
275 * @brief Returns @c *this shifted right by @p shift bits (logical, zero-fill).
276 *
277 * @details
278 * - Shift <= 0: returns @c *this unchanged.
279 * - Shift >= 128: returns zero.
280 * - Shift in [64, 127]: high bits are shifted into the low word.
281 *
282 * @param shift Number of bit positions to shift right.
283 * @return Shifted value.
284 */
285 Uint128 operator>>(int shift) const noexcept;
286
287 /**
288 * @brief Applies bitwise OR with @p other in-place.
289 *
290 * @param other Right-hand operand.
291 * @return Reference to @c *this.
292 */
293 Uint128& operator|=(const Uint128& other) noexcept;
294
295 /**
296 * @brief Applies bitwise AND with @p other in-place.
297 *
298 * @param other Right-hand operand.
299 * @return Reference to @c *this.
300 */
301 Uint128& operator&=(const Uint128& other) noexcept;
302
303 /**
304 * @brief Applies bitwise XOR with @p other in-place.
305 *
306 * @param other Right-hand operand.
307 * @return Reference to @c *this.
308 */
309 Uint128& operator^=(const Uint128& other) noexcept;
310
311 /**
312 * @brief Shifts @c *this left by @p shift bits in-place.
313 *
314 * @param shift Number of bit positions to shift left.
315 * @return Reference to @c *this.
316 */
317 Uint128& operator<<=(int shift) noexcept;
318
319 /**
320 * @brief Shifts @c *this right by @p shift bits in-place (logical, zero-fill).
321 *
322 * @param shift Number of bit positions to shift right.
323 * @return Reference to @c *this.
324 */
325 Uint128& operator>>=(int shift) noexcept;
326
327 /**
328 * @brief Returns @c true if @c *this equals @p other.
329 *
330 * @param other Right-hand operand.
331 * @return @c true if high and low words are both equal.
332 */
333 [[nodiscard]] bool operator==(const Uint128& other) const noexcept;
334
335 /**
336 * @brief Returns @c true if @c *this does not equal @p other.
337 *
338 * @param other Right-hand operand.
339 * @return @c true if any word differs.
340 */
341 [[nodiscard]] bool operator!=(const Uint128& other) const noexcept;
342
343 /**
344 * @brief Returns @c true if @c *this is less than @p other.
345 *
346 * @details
347 * Compares the high word first; if equal, compares the low word.
348 *
349 * @param other Right-hand operand.
350 * @return @c true if @c *this < @p other.
351 */
352 [[nodiscard]] bool operator<(const Uint128& other) const noexcept;
353
354 /**
355 * @brief Returns @c true if @c *this is greater than @p other.
356 *
357 * @param other Right-hand operand.
358 * @return @c true if @c *this > @p other.
359 */
360 [[nodiscard]] bool operator>(const Uint128& other) const noexcept;
361
362 /**
363 * @brief Returns @c true if @c *this is less than or equal to @p other.
364 *
365 * @param other Right-hand operand.
366 * @return @c true if @c *this <= @p other.
367 */
368 [[nodiscard]] bool operator<=(const Uint128& other) const noexcept;
369
370 /**
371 * @brief Returns @c true if @c *this is greater than or equal to @p other.
372 *
373 * @param other Right-hand operand.
374 * @return @c true if @c *this >= @p other.
375 */
376 [[nodiscard]] bool operator>=(const Uint128& other) const noexcept;
377
378 /**
379 * @brief Pre-increment: increments the value by one and returns @c *this.
380 *
381 * @details
382 * Carry from the low word is propagated to the high word.
383 *
384 * @return Reference to the incremented value.
385 */
386 Uint128& operator++() noexcept;
387
388 /**
389 * @brief Post-increment: increments the value by one and returns the previous value.
390 *
391 * @return Copy of the value before incrementing.
392 */
393 Uint128 operator++(int) noexcept;
394
395 /**
396 * @brief Pre-decrement: decrements the value by one and returns @c *this.
397 *
398 * @details
399 * Borrow from the low word underflow is propagated to the high word.
400 *
401 * @return Reference to the decremented value.
402 */
403 Uint128& operator--() noexcept;
404
405 /**
406 * @brief Post-decrement: decrements the value by one and returns the previous value.
407 *
408 * @return Copy of the value before decrementing.
409 */
410 Uint128 operator--(int) noexcept;
411
412 /**
413 * @brief Returns the upper 64 bits of the 128-bit value.
414 *
415 * @return High 64-bit word.
416 */
417 [[nodiscard]] uint64_t get_high() const noexcept;
418
419 /**
420 * @brief Returns the lower 64 bits of the 128-bit value.
421 *
422 * @return Low 64-bit word.
423 */
424 [[nodiscard]] uint64_t get_low() const noexcept;
425
426 /**
427 * @brief Writes the hexadecimal string representation of the value to @p os.
428 *
429 * @param os Output stream.
430 * @param value Value to print.
431 * @return Reference to @p os.
432 */
433 VLINK_EXPORT friend std::ostream& operator<<(std::ostream& os, const Uint128& value) noexcept;
434
435 private:
436 VLINK_EXPORT static int clz64(uint64_t x) noexcept;
437
438 VLINK_EXPORT static void mul_64_128(uint64_t a, uint64_t b, uint64_t& hi, uint64_t& lo) noexcept;
439
440 VLINK_EXPORT static uint64_t add64_carry(uint64_t a, uint64_t b, uint64_t& carry_out) noexcept;
441
442 VLINK_EXPORT static void add_128_with64(uint64_t& high, uint64_t& low, uint64_t add_low,
443 uint64_t add_high = 0) noexcept;
444
445 VLINK_EXPORT static Uint128 mul_u128_fallback(const Uint128& x, const Uint128& y) noexcept;
446
447 VLINK_EXPORT static std::pair<Uint128, Uint128> u128_divmod(const Uint128& dividend, const Uint128& divisor);
448
449 uint64_t high_{0};
450 uint64_t low_{0};
451};
452
454
455////////////////////////////////////////////////////////////////
456/// Details
457////////////////////////////////////////////////////////////////
458
459inline Uint128::Uint128(uint64_t high, uint64_t low) noexcept : high_(high), low_(low) {}
460
461#if defined(__SIZEOF_INT128__)
462inline Uint128::operator __uint128_t() const noexcept { return (static_cast<__uint128_t>(high_) << 64) | low_; }
463#endif
464
465inline Uint128 Uint128::operator+(const Uint128& other) const noexcept {
466 Uint128 r = *this;
467 r += other;
468
469 return r;
470}
471
472inline Uint128 Uint128::operator-(const Uint128& other) const noexcept {
473 Uint128 r = *this;
474 r -= other;
475
476 return r;
477}
478
479inline Uint128 Uint128::operator*(const Uint128& other) const noexcept {
480 Uint128 r = *this;
481 r *= other;
482
483 return r;
484}
485
486inline Uint128 Uint128::operator/(const Uint128& other) const { return u128_divmod(*this, other).first; }
487
488inline Uint128 Uint128::operator%(const Uint128& other) const { return u128_divmod(*this, other).second; }
489
490inline Uint128& Uint128::operator+=(const Uint128& other) noexcept {
491 uint64_t old_low = low_;
492
493 low_ += other.low_;
494
495 uint64_t carry = (low_ < old_low) ? 1 : 0;
496
497 high_ += other.high_ + carry;
498
499 return *this;
500}
501
502inline Uint128& Uint128::operator-=(const Uint128& other) noexcept {
503 uint64_t borrow = (low_ < other.low_) ? 1 : 0;
504
505 low_ -= other.low_;
506 high_ = high_ - other.high_ - borrow;
507
508 return *this;
509}
510
511inline Uint128& Uint128::operator*=(const Uint128& other) noexcept {
512#if defined(__SIZEOF_INT128__)
513 __uint128_t lhs = (static_cast<__uint128_t>(high_) << 64) | low_;
514 __uint128_t rhs = (static_cast<__uint128_t>(other.high_) << 64) | other.low_;
515 __uint128_t res = lhs * rhs;
516
517 high_ = static_cast<uint64_t>(res >> 64);
518 low_ = static_cast<uint64_t>(res);
519#else
520 Uint128 r = mul_u128_fallback(*this, other);
521
522 high_ = r.high_;
523 low_ = r.low_;
524#endif
525 return *this;
526}
527
528inline Uint128& Uint128::operator/=(const Uint128& other) {
529 auto qr = u128_divmod(*this, other);
530
531 high_ = qr.first.high_;
532 low_ = qr.first.low_;
533
534 return *this;
535}
536
537inline Uint128& Uint128::operator%=(const Uint128& other) {
538 auto qr = u128_divmod(*this, other);
539
540 high_ = qr.second.high_;
541 low_ = qr.second.low_;
542
543 return *this;
544}
545
546inline Uint128 Uint128::operator|(const Uint128& other) const noexcept {
547 return Uint128(high_ | other.high_, low_ | other.low_);
548}
549
550inline Uint128 Uint128::operator&(const Uint128& other) const noexcept {
551 return Uint128(high_ & other.high_, low_ & other.low_);
552}
553
554inline Uint128 Uint128::operator^(const Uint128& other) const noexcept {
555 return Uint128(high_ ^ other.high_, low_ ^ other.low_);
556}
557
558inline Uint128 Uint128::operator~() const noexcept { return Uint128(~high_, ~low_); }
559
560inline Uint128 Uint128::operator<<(int shift) const noexcept {
561 if (shift <= 0) {
562 return *this;
563 }
564
565 if (shift >= 128) {
566 return Uint128(0, 0);
567 }
568
569 if (shift >= 64) {
570 return Uint128(low_ << (shift - 64), 0);
571 }
572
573 uint64_t new_high = (high_ << shift) | (low_ >> (64 - shift));
574 uint64_t new_low = low_ << shift;
575
576 return Uint128(new_high, new_low);
577}
578
579inline Uint128 Uint128::operator>>(int shift) const noexcept {
580 if (shift <= 0) {
581 return *this;
582 }
583
584 if (shift >= 128) {
585 return Uint128(0, 0);
586 }
587
588 if (shift >= 64) {
589 return Uint128(0, high_ >> (shift - 64));
590 }
591
592 uint64_t new_low = (low_ >> shift) | (high_ << (64 - shift));
593 uint64_t new_high = high_ >> shift;
594
595 return Uint128(new_high, new_low);
596}
597
598inline Uint128& Uint128::operator|=(const Uint128& other) noexcept {
599 high_ |= other.high_;
600 low_ |= other.low_;
601
602 return *this;
603}
604
605inline Uint128& Uint128::operator&=(const Uint128& other) noexcept {
606 high_ &= other.high_;
607 low_ &= other.low_;
608
609 return *this;
610}
611
612inline Uint128& Uint128::operator^=(const Uint128& other) noexcept {
613 high_ ^= other.high_;
614 low_ ^= other.low_;
615
616 return *this;
617}
618
619inline Uint128& Uint128::operator<<=(int shift) noexcept {
620 if (shift <= 0) {
621 return *this;
622 }
623
624 if (shift >= 128) {
625 high_ = 0;
626 low_ = 0;
627
628 return *this;
629 }
630
631 if (shift >= 64) {
632 high_ = (low_ << (shift - 64));
633 low_ = 0;
634 } else {
635 uint64_t nh = (high_ << shift) | (low_ >> (64 - shift));
636 uint64_t nl = low_ << shift;
637
638 high_ = nh;
639 low_ = nl;
640 }
641
642 return *this;
643}
644
645inline Uint128& Uint128::operator>>=(int shift) noexcept {
646 if (shift <= 0) {
647 return *this;
648 }
649
650 if (shift >= 128) {
651 high_ = 0;
652 low_ = 0;
653 return *this;
654 }
655
656 if (shift >= 64) {
657 low_ = (high_ >> (shift - 64));
658 high_ = 0;
659 } else {
660 uint64_t nl = (low_ >> shift) | (high_ << (64 - shift));
661 uint64_t nh = high_ >> shift;
662
663 high_ = nh;
664 low_ = nl;
665 }
666
667 return *this;
668}
669
670inline bool Uint128::operator==(const Uint128& other) const noexcept {
671 return high_ == other.high_ && low_ == other.low_;
672}
673
674inline bool Uint128::operator!=(const Uint128& other) const noexcept { return !(*this == other); }
675
676inline bool Uint128::operator<(const Uint128& other) const noexcept {
677 return (high_ < other.high_) || (high_ == other.high_ && low_ < other.low_);
678}
679
680inline bool Uint128::operator>(const Uint128& other) const noexcept { return other < *this; }
681
682inline bool Uint128::operator<=(const Uint128& other) const noexcept { return !(other < *this); }
683
684inline bool Uint128::operator>=(const Uint128& other) const noexcept { return !(*this < other); }
685
686inline Uint128& Uint128::operator++() noexcept {
687 uint64_t old_low = low_;
688
689 low_ += 1;
690
691 if (low_ < old_low) {
692 ++high_;
693 }
694
695 return *this;
696}
697
698inline Uint128 Uint128::operator++(int) noexcept {
699 Uint128 tmp = *this;
700
701 ++(*this);
702
703 return tmp;
704}
705
706inline Uint128& Uint128::operator--() noexcept {
707 uint64_t old_low = low_;
708 low_ -= 1;
709
710 if (old_low == 0) {
711 --high_;
712 }
713
714 return *this;
715}
716
717inline Uint128 Uint128::operator--(int) noexcept {
718 Uint128 tmp = *this;
719
720 --(*this);
721
722 return tmp;
723}
724
725inline uint64_t Uint128::get_high() const noexcept { return high_; }
726
727inline uint64_t Uint128::get_low() const noexcept { return low_; }
728
729template <typename T>
730inline constexpr Uint128::Uint128(T v) noexcept {
731 // static_assert(std::is_integral_v<T>, "Uint128(T): T must be an integral type");
732
733#if defined(__SIZEOF_INT128__)
734 if constexpr (std::is_same_v<__uint128_t, T>) {
735 high_ = static_cast<uint64_t>(v >> 64);
736 low_ = static_cast<uint64_t>(v);
737
738 return;
739 }
740#endif
741
742 if constexpr (std::is_constructible_v<uint64_t, T>) {
743 high_ = 0;
744 low_ = v;
745 }
746}
747
748} // namespace vlink
749
750namespace std {
751
752/**
753 * @brief @c std::hash specialisation for @c vlink::Uint128.
754 *
755 * @details
756 * Enables @c vlink::Uint128 (and the @c vlink::uint128_t alias) to be used as a key in
757 * @c std::unordered_map, @c std::unordered_set, and similar hash-based containers.
758 *
759 * The hash function combines the high and low 64-bit words to produce a @c size_t result.
760 */
761template <>
762struct hash<vlink::Uint128> {
763 /**
764 * @brief Computes the hash of @p value.
765 *
766 * @param value The 128-bit value to hash.
767 * @return Hash value derived from both the high and low 64-bit words.
768 */
769 VLINK_EXPORT size_t operator()(const vlink::Uint128& value) const noexcept;
770};
771
772} // namespace std
Platform-independent macro definitions for the VLink library.
#define VLINK_EXPORT
定义 macros.h:85
STL namespace