Last active
April 2, 2017 07:08
-
-
Save xtozero/8ead227402d9272da6b055863c96f151 to your computer and use it in GitHub Desktop.
Detect implicit conversion in compile time
This file contains hidden or 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 <iostream> | |
| #include <utility> | |
| #include <string> | |
| template <typename T, typename U, typename... R> | |
| class TypeChecker : public TypeChecker<T, R...> | |
| { | |
| public: | |
| using TypeChecker<T, R...>::TypeChecker; | |
| using TypeChecker<T, R...>::operator=; | |
| template <typename ANY> | |
| TypeChecker( ANY&& arg ) : TypeChecker<T, R...>{ arg } | |
| { | |
| TypeChecker<T, R...>::CheckType( std::forward<ANY>( arg ), | |
| std::is_same<typename std::decay<ANY>::type, | |
| typename std::decay<U>::type>() ); | |
| } | |
| template <typename ANY> | |
| TypeChecker& operator=( ANY&& arg ) | |
| { | |
| TypeChecker<T, R...>::CheckType( std::forward<ANY>( arg ), | |
| std::is_same<typename std::decay<ANY>::type, | |
| typename std::decay<U>::type>() ); | |
| TypeChecker<T, R...>::operator=( std::forward<ANY>( arg ) ); | |
| return *this; | |
| } | |
| }; | |
| template <typename T, typename U> | |
| class TypeChecker<T, U> : public T | |
| { | |
| public: | |
| using T::T; | |
| using T::operator=; | |
| template <typename ANY> | |
| TypeChecker( ANY&& arg ) : T{ std::forward<ANY>( arg ) } | |
| { | |
| CheckType( std::forward<ANY>( arg ), | |
| std::is_same<typename std::decay<ANY>::type, | |
| typename std::decay<U>::type>() ); | |
| } | |
| template <typename ANY> | |
| TypeChecker& operator=( ANY&& arg ) | |
| { | |
| CheckType( std::forward<ANY>( arg ), | |
| std::is_same<typename std::decay<ANY>::type, | |
| typename std::decay<U>::type>() ); | |
| T::operator=( std::forward<ANY>( arg ) ); | |
| return *this; | |
| } | |
| protected: | |
| template <typename ANY> | |
| void CheckType( ANY&& arg, std::true_type ) { static_assert(false, "Invalid Data Type used"); } | |
| template <typename ANY> | |
| void CheckType( ANY&&, std::false_type ) {} | |
| }; | |
| using TCString = TypeChecker<std::string, bool>; | |
| void UseTypeCheckString( const TCString& arg ) | |
| { | |
| std::cout << arg << std::endl; | |
| } | |
| void UnuseTypeCheckString( const std::string& arg ) | |
| { | |
| std::cout << arg << std::endl; | |
| } | |
| class Int | |
| { | |
| public: | |
| Int( ... ) {} | |
| }; | |
| using TCInt = TypeChecker<Int, bool, long>; | |
| int main() | |
| { | |
| char c_str[] = "c-style string"; | |
| UseTypeCheckString( c_str ); // ok | |
| std::string str = "string variable"; | |
| UseTypeCheckString( str ); // ok | |
| const char* const_c_str = "cibst c-style string"; | |
| UseTypeCheckString( const_c_str ); // ok | |
| const std::string const_str = "const string"; | |
| UseTypeCheckString( const_str ); // ok | |
| UnuseTypeCheckString( false ); // compile success but runtime error | |
| UseTypeCheckString( false ); // compile time error | |
| TCInt a( 'c' ); // ok | |
| TCInt b( 1 ); // ok | |
| TCInt c( 3.14 ); // ok | |
| TCInt d( false ); // compile time error | |
| TCInt e( 1L ); // compile time error | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment