Skip to content

Instantly share code, notes, and snippets.

@xtozero
Last active April 2, 2017 07:08
Show Gist options
  • Save xtozero/8ead227402d9272da6b055863c96f151 to your computer and use it in GitHub Desktop.
Save xtozero/8ead227402d9272da6b055863c96f151 to your computer and use it in GitHub Desktop.
Detect implicit conversion in compile time
#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