template< typename U, typename... args >
void mapClasses()
{
// ...
if constexpr( sizeof...( args ) > 0 ) // Все понятно и без слов.
{
mapClasses<args...>();
}
}
template< typename... args >
struct Map;
template< typename U >
struct Map<U>
{
static inline void mapClasses()
{
// ...
}
};
template< typename U, typename... args >
struct Map<U, args...>
{
static inline void mapClasses()
{
Map<U>::mapClasses();
Map<args...>::mapClasses();
}
};
template< typename U >
void mapClasses()
{
// ...
}
// SFINAE тут (аргумент функции) выключит вывод шаблона при пустом списке полей.
// В этом случае доступным остается только верхний экземпляр функции.
template< typename U, typename... args >
void mapClasses( char (*)[ sizeof...( args ) > 0 ] = 0 )
{
mapClasses<U>();
mapClasses<args...>();
}
Сам класс в .h, а его описание в .cpp.
А потом к основному main.cpp подключаю просто файл .h
Получается какой-то костыль.
И почему крупные компании не могут реализовать свою такую технологию, а покупают ее у других?
А почему так мало игр ее использует?
Теперь стал интерисовать вопрос - как прикрутить к этому всему физику.
auto out = in;
The lifetime of a temporary object may be extended by binding to a const lvalue reference or to an rvalue reference (since C++11), see reference initialization for details.
enum class AllowedTypes : uint8_t
{
Int8 = 0,
Uint8,
Int16,
Uint16,
};
template< AllowedTypes TYPE >
struct AllowedType;
template<>
struct AllowedType<AllowedTypes::Int8>
{
using Type = int8_t;
};
template<>
struct AllowedType<AllowedTypes::Uint8>
{
using Type = uint8_t;
};
template<>
struct AllowedType<AllowedTypes::Int16>
{
using Type = int16_t;
};
template<>
struct AllowedType<AllowedTypes::Uint16>
{
using Type = uint16_t;
};
template< AllowedTypes TYPE >
struct spi
{
typename AllowedType<TYPE>::Type* p_tx = nullptr;
constexpr spi() {};
};
// Example program
#include <typeinfo>
#include <iostream>
#include <string>
#include <cstdint>
enum class AllowedTypes : uint8_t
{
Int8 = 0,
Uint8,
Int16,
Uint16,
};
template< AllowedTypes TYPE >
struct AllowedType;
template<>
struct AllowedType<AllowedTypes::Int8>
{
using Type = int8_t;
};
template<>
struct AllowedType<AllowedTypes::Uint8>
{
using Type = uint8_t;
};
template<>
struct AllowedType<AllowedTypes::Int16>
{
using Type = int16_t;
};
template<>
struct AllowedType<AllowedTypes::Uint16>
{
using Type = uint16_t;
};
template< AllowedTypes TYPE >
using TypeFor = typename AllowedType<TYPE>::Type;
template< AllowedTypes TYPE >
struct spi
{
TypeFor<TYPE>* p_tx = nullptr;
constexpr spi() {};
};
int main()
{
spi<AllowedTypes::Int8> spi1;
std::cout << typeid( *spi1.p_tx ).name() << " " << sizeof( *spi1.p_tx ) << std::endl;
spi<AllowedTypes::Uint16> spi2;
std::cout << typeid( *spi2.p_tx ).name() << " " << sizeof( *spi2.p_tx ) << std::endl;
return 0;
}
2. Писать на С++/CLI. Только тут я не понимаю, как их совместить.
Ну написал я код на С++/CLI, а как мне его в проект , написанный на С# вставить ?
class Foo
{
public:
void baz1( int bar )
{
this->bar = bar;
}
void baz2( int bar )
{
Foo::bar = bar;
}
void baz3( int bar )
{
this->Foo::bar = bar;
}
public:
int bar = 0;
};
template <class > friend std::ostream& operator<<(std::ostream& s, Vec2<t>& v);
// PlatformSpecificFile.Windows.h
class PlatformSpecificFile
{
// Platform-specific interface.
public:
inline ::HANDLE GetHandle() const { return m_handle; };
// Platform-independent interface, but platform-dependent implementation.
public:
// RAII.
PlatformSpecificFile() = delete;
PlatformSpecificFile(
const std::string& path,
const OpeningMode desired_mode,
const AccessOptions& desired_access,
const SharingOptions& desired_sharing
);
virtual ~PlatformSpecificFile();
void Close();
void Flush();
const size64_t GetSize() const;
const bool Resize( const size64_t new_size );
const size32_t Read( NotNull<uint8_t> buffer, const size32_t buffer_size ) const;
const size32_t Write( NotNull<const uint8_t> buffer, const size32_t buffer_size );
const size64_t Seek( const size64_t offset, const SeekOrientation orientation );
inline const bool IsValid() const { return IsHandleValid( m_handle ); };
private:
::HANDLE m_handle = INVALID_HANDLE_VALUE;
};
// PlatformSpecificFile.Android.h
class PlatformSpecificFile
{
// Platform-specific interface.
public:
inline int GetHandle() const { return m_handle; };
// Platform-independent interface, but platform-dependent implementation.
public:
// RAII.
PlatformSpecificFile() = delete;
PlatformSpecificFile(
const std::string& path,
const OpeningMode desired_mode,
const AccessOptions& desired_access,
const SharingOptions& desired_sharing
);
virtual ~PlatformSpecificFile();
void Close();
void Flush();
const size64_t GetSize() const;
const bool Resize( const size64_t new_size );
const size32_t Read( NotNull<uint8_t> buffer, const size32_t buffer_size ) const;
const size32_t Write( NotNull<const uint8_t> buffer, const size32_t buffer_size );
const size64_t Seek( const size64_t offset, const SeekOrientation orientation );
inline const bool IsValid() const { return m_handle >= 0; };
private:
int m_handle = -1;
};
// File.h
class File final : public PlatformSpecificFile
{
public:
using PlatformSpecificFile::PlatformSpecificFile;
const size64_t GetPosition() const; // Seek( 0, SeekOrientation::FromPosition );
const bool SetPosition( const size64_t position ); // Seek( position, SeekOrientation::FromBeginning );
const bool IsFileEnded() const; // GetPosition() == getSize();
};
template< typename TInterface, typename... TArguments >
class AbstractFactory final
{
public:
// Produce the implementation, but return the pointer to interface.
inline std::shared_ptr<TInterface> Produce( const std::string& implementation_name, TArguments... arguments )
{
auto found_function = m_factory_functions.find( implementation_name );
return ( found_function == m_factory_functions.end() )? std::shared_ptr<TInterface>{} : found_function->second( std::forward<TArguments>( arguments )... );
};
// Define the implementation.
template< typename TImplementation >
inline const bool DefineImplementation()
{
return DefineImplementation<TImplementation>( TImplementation::ClassName() );
};
// Define the implementation.
template< typename TImplementation >
inline const bool DefineImplementation( const std::string& implementation_name )
{
// Abort the incorrect registration.
static_assert( std::is_base_of<TInterface, TImplementation>::value, "Implementation may only be derived from interface of Factory." );
auto found_function = m_factory_functions.find( implementation_name );
if( found_function == m_factory_functions.end() )
{
m_factory_functions[ implementation_name ] = &AbstractFactory<TInterface, TArguments...>::template ConstructImplementation<TImplementation>;
return true;
};
return false;
};
// Check the implementation name is already defined.
inline const bool IsImplementationDefined( const std::string& implementation_name ) const
{
return m_factory_functions.find( implementation_name ) != m_factory_functions.end();
};
private:
// The factory function just produce implementation.
template< typename TImplementation >
static std::shared_ptr<TInterface> ConstructImplementation( TArguments... arguments )
{
return std::static_pointer_cast<TInterface>(
std::make_shared<TImplementation>( std::forward<TArguments>( arguments )... )
);
};
private:
// Factory function produces the implementations of TInterface.
using FactoryFunction = std::shared_ptr<TInterface> (*)( TArguments... arguments );
std::unordered_map<std::string, FactoryFunction> m_factory_functions;
};