Skip to content

Instantly share code, notes, and snippets.

@pabigot
Last active August 29, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pabigot/8775866 to your computer and use it in GitHub Desktop.
Save pabigot/8775866 to your computer and use it in GitHub Desktop.
Examples for a blog post on C++ overloading
/* Demonstrate technique for verifying that a member function with a
* specific signature exists. */
#include <utility>
#include <type_traits>
#include <iostream>
#include <vector>
namespace details {
template <typename T,
typename = std::enable_if<std::is_same<void, decltype(std::declval<T>().clear())>::value>>
void clear_ (T& value, int)
{
std::cout << "invoking clear\n";
value.clear();
}
template <typename T>
void clear_ (T& value, long)
{
std::cout << "move-assigning default\n";
value = std::move(T{});
}
} // ns details
template <typename T>
void clear (T& value)
{
return details::clear_(value, 0);
}
int main (int argc, char * argv [])
{
std::vector<int> v;
int i{5};
v.push_back(i);
std::cout << "Pre: i=" << i << "; v has " << v.size() << " members\n";
std::cout << "For vector: ";
clear(v);
std::cout << "For int: ";
clear(i);
std::cout << "Post: i=" << i << "; v has " << v.size() << " members\n";
}
# Normal use is GNUC in $(GCC_ROOT).
# Alternative is clang++ in $(CLANG_ROOT), enable with WITH_CLANG=1
# libc++ enabled with WITH_LIBCPP=1 (defaults WITH_CLANG=1)
CXX_STD=c++1y
GCC_ROOT=/usr/local/gcc
CLANG_ROOT=/usr/local/clang
# This is how libc++ spells itself; it's not a C preprocessor library
WITH_LIBCPP ?= 0
WITH_CLANG ?= $(WITH_LIBCPP)
WARN_CXXFLAGS=-Wall -Werror
OPT_CXXFLAGS=-g -O2
CPPFLAGS=-DWITH_BOOST=$(WITH_BOOST) $(AUX_CPPFLAGS)
CXXFLAGS=-std=$(CXX_STD) $(WARN_CXXFLAGS) $(OPT_CXXFLAGS) $(AUX_CXXFLAGS)
LDFLAGS?=
LINK.o=$(LINK.cc)
ifneq ($(WITH_CLANG), 0)
TOOLCHAIN_ROOT=$(CLANG_ROOT)
CXX=$(CLANG_ROOT)/bin/clang++
ifneq ($(WITH_LIBCPP), 0)
CPPFLAGS += -I$(CLANG_ROOT)/include/c++/v1
CXXFLAGS += -stdlib=libc++
LDFLAGS += -L$(CLANG_ROOT)/lib/ -Wl,-rpath,$(CLANG_ROOT)/lib/
endif # WITH_LIBCPP
else # WITH_CLANG
TOOLCHAIN_ROOT=$(GCC_ROOT)
CXX=$(GCC_ROOT)/bin/g++
endif # WITH_CLANG
LDFLAGS += -Wl,-rpath,$(TOOLCHAIN_ROOT)/lib64:$(TOOLCHAIN_ROOT)/lib32:$(TOOLCHAIN_ROOT)/lib
CLEAN ?=
REALCLEAN ?=
CASES = no-check ei-check sa-check sa-helper-check
all: overload
CLEAN += overload
CLEAN += check-sig-match
.PHONY: clean realclean
clean:
-rm -rf $(CLEAN)
-rm -f *.o *~
realclean: clean
-rm -rf $(REALCLEAN)
/* From: https://ideone.com/IB6tIR
* Documented at: http://flamingdangerzone.com/cxx11/2013/03/11/overload-ranking.html
* By: http://stackoverflow.com/users/500104/xeo
* Modified: pabigot 20140201
*/
#include <type_traits>
#include <iostream>
template<int N, int M>
struct is_multiple_of : std::integral_constant<bool, N % M == 0>{};
template<unsigned I> struct overload_weight : overload_weight<I-1>{};
/* Lowest priority, use for default selection */
template<> struct overload_weight<0>{};
/* Helper constant, kept up to date as overload list is changed */
#define FIZZBUZZ_OVERLOAD_MAX_WEIGHT 10
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 15>::value>::type>
void print_fizzbuzz(overload_weight<10>){ std::cout << "fizzbuzz\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 21>::value>::type>
void print_fizzbuzz(overload_weight<9>){ std::cout << "fizzbeep\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 33>::value>::type>
void print_fizzbuzz(overload_weight<8>){ std::cout << "fizznarf\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 35>::value>::type>
void print_fizzbuzz(overload_weight<7>){ std::cout << "buzzbeep\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 55>::value>::type>
void print_fizzbuzz(overload_weight<6>){ std::cout << "buzznarf\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 77>::value>::type>
void print_fizzbuzz(overload_weight<5>){ std::cout << "beepnarf\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 3>::value>::type>
void print_fizzbuzz(overload_weight<4>){ std::cout << "fizz\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 5>::value>::type>
void print_fizzbuzz(overload_weight<3>){ std::cout << "buzz\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 7>::value>::type>
void print_fizzbuzz(overload_weight<2>){ std::cout << "beep\n"; }
template<unsigned N, typename = typename std::enable_if<is_multiple_of<N, 11>::value>::type>
void print_fizzbuzz(overload_weight<1>){ std::cout << "narf\n"; }
/* No conditional on default case */
template<unsigned N>
void print_fizzbuzz(overload_weight<0>){ std::cout << N << "\n"; }
template<unsigned N = 1>
void do_fizzbuzz(){
print_fizzbuzz<N>(overload_weight<FIZZBUZZ_OVERLOAD_MAX_WEIGHT>{});
do_fizzbuzz<N+1>();
}
template<>
void do_fizzbuzz<100>(){
print_fizzbuzz<100>(overload_weight<FIZZBUZZ_OVERLOAD_MAX_WEIGHT>{});
}
int main(){
do_fizzbuzz();
}
1
2
fizz
4
buzz
fizz
beep
8
fizz
buzz
narf
fizz
13
beep
fizzbuzz
16
17
fizz
19
buzz
fizzbeep
narf
23
fizz
buzz
26
fizz
beep
29
fizzbuzz
31
32
fizznarf
34
buzzbeep
fizz
37
38
fizz
buzz
41
fizzbeep
43
narf
fizzbuzz
46
47
fizz
beep
buzz
fizz
52
53
fizz
buzznarf
beep
fizz
58
59
fizzbuzz
61
62
fizzbeep
64
buzz
fizznarf
67
68
fizz
buzzbeep
71
fizz
73
74
fizzbuzz
76
beepnarf
fizz
79
buzz
fizz
82
83
fizzbeep
buzz
86
fizz
narf
89
fizzbuzz
beep
92
fizz
94
buzz
fizz
97
beep
fizznarf
buzz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment