Files supporting Diagnostics in Template Meta-Programming in C++
Last active
August 29, 2015 13:55
-
-
Save pabigot/8755520 to your computer and use it in GitHub Desktop.
Support for Diagnostics in Template Metaprogramming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <type_traits> | |
/* Provide the algorithm only if the expectations are met */ | |
template <typename T1, typename T2, | |
typename = typename std::enable_if<std::is_assignable<T1, T2>::value>::type> | |
void useit (T1& t1, T2 t2) | |
{ | |
t1 = t2; | |
} | |
int main () | |
{ | |
std::wstring s1{L"wide"}; | |
std::string t1{"narrow"}; | |
useit(t1, s1); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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: $(CASES:%=%.err) | |
CLEAN += *.err | |
%.err: %.cc | |
-$(LINK.cc) $^ $(LDLIBS) > $@ 2>&1 | |
.PHONY: clean realclean | |
clean: | |
-rm -rf $(CLEAN) | |
-rm -f *.o *~ | |
realclean: clean | |
-rm -rf $(REALCLEAN) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
template <typename T1, typename T2> | |
void useit (T1& t1, T2 t2) | |
{ | |
t1 = t2; | |
} | |
int main () | |
{ | |
std::wstring s1{L"wide"}; | |
std::string t1{"narrow"}; | |
useit(t1, s1); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <type_traits> | |
template <typename T1, typename T2> | |
void useit_ (T1& t1, T2 t2) | |
{ | |
t1 = t2; | |
} | |
/* Generate a diagnostic if the expectations aren't met, but defer the | |
* mis-use to another function */ | |
template <typename T1, typename T2> | |
void useit (T1& t1, T2 t2) | |
{ | |
static_assert(template_types_ok::value, "cannot assign T2 to T1"); | |
useit_(t1, t2); | |
} | |
int main () | |
{ | |
std::wstring s1{L"wide"}; | |
std::string t1{"narrow"}; | |
useit(t1, s1); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <type_traits> | |
/* Provide the algorithm only if the expectations are met */ | |
template <typename T1, typename T2, | |
typename = typename std::enable_if<std::is_assignable<T1, T2>::value>::type> | |
void useit_ (T1& t1, T2 t2, std::true_type template_types_ok) | |
{ | |
t1 = t2; | |
} | |
/* Provide a no-op that doesn't produce errors when the expectations | |
* are not met. */ | |
template <typename T1, typename T2> | |
void useit_ (T1&, T2, std::false_type template_types_ok) | |
{ } | |
/* Bleat in distress when the template types don't satisfy | |
* expectations, but unconditionally delegate to an implementation | |
* that won't produce compiler errors in either case. */ | |
template <typename T1, typename T2> | |
void useit (T1& t1, T2 t2) | |
{ | |
using template_types_ok = std::is_assignable<T1, T2>; | |
static_assert(template_types_ok::value, "cannot assign T2 to T1"); | |
useit_(t1, t2, typename template_types_ok::type()); | |
} | |
int main () | |
{ | |
std::wstring s1{L"wide"}; | |
std::string t1{"narrow"}; | |
useit(t1, s1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment