I would like to achieve something like that:
template<class... Args>
class MyClass{
public:
MyClass(){
for(auto arg : {sizeof(Args)...})
std::cout<<arg<<std::endl;
}
};
But with one simple exception. The type char* should return 0(or everything else, what will be distinct from an int).
How about the following?
/* heavily borrowed from IBM's variadic template page */
#include <iostream>
using namespace std;
/*
template<typename T> struct type_size{
operator int(){return sizeof( T );}
};
template<> struct type_size <char *>{
operator int(){return 0;}
};
*/
/* as per Mattieu M.'s suggestion */
template<typename T> constexpr size_t type_size(T dummy) {
return sizeof dummy;
}
constexpr size_t type_size(char *){
return 0;
}
template <typename...I> struct container{
container(){
int array[sizeof...(I)]={type_size<I>()...};
printf("container<");
for(int count = 0; count<sizeof...(I); count++){
if(count>0){
printf(",");
}
printf("%d", array[count]);
}
printf(">\n");
}
};
int main(void){
container<int, short, char *> g;
}
template<typename T>
std::size_t size()
{
return sizeof(T);
}
template<>
std::size_t size<char*>()
{
return 0;
}
template<class... Args>
class MyClass{
public:
MyClass()
{
std::initializer_list<char> { (std::cout << size<Args>(), void(), char {})... };
}
};
Although in truth I have an EXPAND macro that hides the std::initializer_list ugliness (not to mention void() + comma operator trick) such that it would look like EXPAND( std::cout << size<Args>() ).
Related
I'm working on a C++11 wrapper around a C api. The C api offers a bunch of getters for various types, with a different name for each type. Values are retrieved by array of a given size, known at compilation.
I want to give the type and the array size by template, to call the right function.
#include <string>
#include <iostream>
template <typename T>
struct make_stop {
constexpr static bool value = false;
};
class Foo
{
public:
Foo() : i(42) {}
template<typename T, size_t n>
T get();
private:
int i = 0;
};
template<typename T, size_t n>
T Foo::get() { static_assert(make_stop<T>::value); return T(); }
template<int, size_t n>
int Foo::get() { return i + n; }
int main() {
Foo foo;
int i = foo.get<int, 4>();
double f = foo.get<double, 2>();
return 0;
}
But it fails to match the right function
main.cpp:26:5: error: no declaration matches 'int Foo::get()'
int Foo::get() { return i + n; }
^~~
main.cpp:15:7: note: candidate is: 'template<class T, long unsigned int n> T Foo::get()'
T get();
its a bit vauge from your question, but assuming you are wanting to index into some c- arrays and return the value at I you can't specialize function templates like you want, but you can use some tags instead, something like..
class Foo
{
public:
Foo() : is{1,2,3,4,5,6,7,8,9,10},ds{1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.1} {}
template <typename T> struct type_c{};
template <size_t I> struct int_c{};
template<typename T,size_t I>
auto get()
{ return get_impl(type_c<T>(),int_c<I>()); }
private:
template <size_t I>
auto get_impl(type_c<int>,int_c<I>)
{ return is[I]; }
template <size_t I>
auto get_impl(type_c<double>,int_c<I>)
{ return ds[I]; }
int is[10];
double ds[10];
};
int main() {
Foo foo;
int i = foo.get<int,0>();
double d = foo.get<double,2>();
std::cout << i << " " << d << std::endl;
return 0;
}
Demo
If I understood you correctly you want to partially specialize get for T. Unfortunately partial specialization for methods is not allowed by the standard. You can however get around this with a static method on a class templated by T and specializing the class.
Like this:
template <class T> struct Foo_helper;
struct Foo
{
Foo() : i{42} {}
template<class T, std::size_t N>
T get()
{
return Foo_helper<T>::template get<N>(*this);
}
int i = 0;
};
template <class T> struct Foo_helper {};
// specialize Foo_helper for each type T you wish to support:
template <> struct Foo_helper<int>
{
template <std::size_t N>
static int get(const Foo& foo) { return foo.i + N; }
};
template <> struct Foo_helper<double>
{
template <std::size_t N>
static double get(const Foo& foo) { return foo.i + N; }
};
int main()
{
Foo foo{};
int i = foo.get<int, 4>();
double d = foo.get<double, 2>();
}
I am writing an Abstract Factory using C++ templates and was hit by a small obstacle. Namely, a generic class T may provide one or more of the following ways to construct objects:
static T* T::create(int arg);
T(int arg);
T();
I am writing the abstract factory class so that it can automatically try these three potential constructions in the given order:
template <class T>
class Factory {
public:
T* create(int arg) {
return T::create(arg); // first preference
return new T(arg); // this if above does not exist
return new T; // this if above does not exist
// compiler error if none of the three is provided by class T
}
};
How do I achieve this with C++ template? Thank you.
Something along this line should work:
struct S { static auto create(int) { return new S; } };
struct T { T(int) {} };
struct U {};
template<int N> struct tag: tag<N-1> {};
template<> struct tag<0> {};
class Factory {
template<typename C>
auto create(tag<2>, int N) -> decltype(C::create(N)) {
return C::create(N);
}
template<typename C>
auto create(tag<1>, int N) -> decltype(new C{N}) {
return new C{N};
}
template<typename C>
auto create(tag<0>, ...) {
return new C{};
}
public:
template<typename C>
auto create(int N) {
return create<C>(tag<2>{}, N);
}
};
int main() {
Factory factory;
factory.create<S>(0);
factory.create<T>(0);
factory.create<U>(0);
}
It's based on sfinae and tag dispatching techniques.
The basic idea is that you forward the create function of your factory to a set of internal functions. These functions test the features you are looking for in order because of the presence of tag and are discarded if the test fail. Because of sfinae, as long as one of them succeeds, the code compiles and everything works as expected.
Here is a similar solution in C++17:
#include <type_traits>
#include <iostream>
#include <utility>
struct S { static auto create(int) { return new S; } };
struct T { T(int) {} };
struct U {};
template<typename C> constexpr auto has_create(int) -> decltype(C::create(std::declval<int>()), bool{}) { return true; }
template<typename C> constexpr auto has_create(char) { return false; }
struct Factory {
template<typename C>
auto create(int N) {
if constexpr(has_create<C>(0)) {
std::cout << "has create" << std::endl;
return C::create(N);
} else if constexpr(std::is_constructible_v<C, int>) {
std::cout << "has proper constructor" << std::endl;
return new C{N};
} else {
std::cout << "well, do it and shut up" << std::endl;
(void)N;
return C{};
}
}
};
int main() {
Factory factory;
factory.create<S>(0);
factory.create<T>(0);
factory.create<U>(0);
}
Thanks to #StoryTeller and #Jarod42 for the help in this difficult morning.
See it up and running on wandbox.
Okay, thanks to the answer by #skypjack I was able to come up with a more compatible solution that works with pre c++11 compilers. The core idea is the same, i.e. using tag dispatching for ordered testing. Instead of relying on decltype, I used sizeof and a dummy class for SFINAE.
struct S { static auto create(int) { return new S; } };
struct T { T(int) {} };
struct U {};
template<class C, int=sizeof(C::create(0))> struct test_1 { typedef int type; };
template<class C, int=sizeof(C(0))> struct test_2 { typedef int type; };
template<class C, int=sizeof(C())> struct test_3 { typedef int type; };
template<int N> struct priority: priority<N-1> {};
template<> struct priority<0> {};
class Factory {
template<typename C>
C* create(priority<2>, typename test_1<C>::type N) {
return C::create(N);
}
template<typename C>
C* create(priority<1>, typename test_2<C>::type N) {
return new C(N);
}
template<typename C>
C* create(priority<0>, typename test_3<C>::type N) {
return new C();
}
public:
template<typename C>
C* create(int N) {
return create<C>(priority<2>(), N);
}
};
int main() {
Factory factory;
factory.create<S>(0);
factory.create<T>(0);
factory.create<U>(0);
}
Not sure if it is even possible to stuff the sizeof part into the private function signatures; if so, we can get rid of the dummy classes as well.(failed) The slightly ugly part is to use constants (0 in this case) for sizeof operator, which may get tricky if the constructors take arguments of very complicated types.
I am new to SFINAE. I have a template that I would like to be able to accept classes that the size could be determined simply calling sizeof(x) or in case the value is dynamic it will require x.size().
I am trying to wrap my head around how as smooth as possible this could looks like and I think interface: size_t size(const Item& item) seems to be good enough.
The following is an example that works:
#include <iostream>
#include <cstdio>
#include <type_traits>
template <typename T>
class Fixed {
public:
typedef T Item;
static const bool kFixedSize = true;
static size_t size() {
return sizeof(T);
}
};
template <typename T>
class Dynamic {
public:
typedef T Item;
static const bool kFixedSize = false;
static size_t size(const T& item) {
return item.size();
}
};
template <typename T>
class Serialize {
public:
template <typename = typename std::enable_if<T::kFixedSize> >
size_t size(typename T::Item&) {
return T::size();
}
template <typename = typename std::enable_if<!T::kFixedSize> >
size_t size(const typename T::Item& item) {
return T::size(item);
}
};
int main() {
Serialize< Fixed<int> > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
Serialize< Dynamic<std::string> > dynamic;
std::cout << dynamic.size("string") << std::endl;
return 0;
}
It has an issues though one is: size_t size(typename T::Item&) and the other is size_t size(const typename T::Item& item) else the compiler compliance that I am overloading the template. The second is it seems like too match very tricky code to achieve the goal - is there better ways to do this?
I believe you want something like this
//class hierarchy to set the priority for type matching
struct second_priority
{
};
struct first_priority : public second_priority
{};
template<typename T>
auto size_impl(T const & data, second_priority t) -> int
{
return sizeof(data);
}
template<typename T>
auto size_impl(T const & data , first_priority t) -> decltype(data.size(),int())
{
return data.size();
}
template<typename T>
int size(T const & data )
{
return size_impl(data,first_priority{});
}
I think #Gautam Jha presented a nice solution using SFINAE. You can shorten it a bit by using ellipsis for the 'else' case, so you don't need to use this auxiliary class and it's inheritance:
template<typename T>
auto size_impl(T const & item, int) -> decltype(item.size())
{
return item.size();
}
template<typename T>
auto size_impl(T const & item, ...) -> size_t
{
return sizeof(T);
}
template<typename T>
auto size(T const & item) -> size_t
{
return size_impl(item, 0);
}
It's cool that you're playing around with SFINAE, but usually there are simpler (i.e. to read and to understand) ways to achieve the same, see the solution of POW (which has unfortunately been deleted).
Since all you want to do is call different functions to get the size in Dynamic or Fixed, you can just implement these classes differently and use them in Serialize:
#include <iostream>
#include <cstdio>
#include <type_traits>
template <typename T>
class Fixed {
public:
typedef T Item;
static size_t size(const T&) {
return sizeof(T);
}
};
template <typename T>
class Dynamic {
public:
typedef T Item;
static size_t size(const T& item) {
return item.size();
}
};
template <typename T>
class Serialize {
public:
size_t size(typename T::Item const& x) {
return T::size(x);
}
};
int main() {
Serialize< Fixed<int> > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
Serialize< Dynamic<std::string> > dynamic;
std::cout << dynamic.size( std::string{"string"} ) << std::endl;
return 0;
}
However, I would consider using a type-trait or a free function to do the same. This would be more extensible, because you have to just provide a new trait or an overload for new types, e.g. some container which has only a length method.
#include <iostream>
#include <cstdio>
#include <type_traits>
size_t size(int) {return sizeof(int);}
size_t size(std::string const& s) {return s.size();}
template<typename T>
struct size_trait
{
};
template<>
struct size_trait<int>
{
static size_t size(int) {return sizeof(int);}
};
template<>
struct size_trait<std::string>
{
static size_t size(std::string const& x) {return x.size();}
};
template <typename T>
class Serialize {
public:
size_t size(T const& x) {
return ::size(x);
}
size_t size_(T const& x) {
return size_trait<T>::size(x);
}
};
int main() {
Serialize< int > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
std::cout << fixed.size_(a) << std::endl;
Serialize< std::string > dynamic;
std::cout << dynamic.size( std::string{"string"} ) << std::endl;
std::cout << dynamic.size_( std::string{"string"} ) << std::endl;
return 0;
}
I'm new in using templates in C++, I want to do different things depending on type used between < and >, so function<int>() and function<char>() won't do the same things.
How can I achieve this?
template<typename T> T* function()
{
if(/*T is int*/)
{
//...
}
if(/*T is char*/)
{
//...
}
return 0;
}
You want to use explicit specialization of your function template:
template<class T> T* function() {
};
template<> int* function<int>() {
// your int* function code here
};
template<> char* function<char>() {
// your char* function code here
};
Create template specializations:
template<typename T> T* function()
{
//general case general code
}
template<> int* function<int>()
{
//specialization for int case.
}
template<> char* function<char>()
{
//specialization for char case.
}
Best practices involves tag dispatch, because specialization is tricky.
Tag dispatch is easier to use quite often:
template<typename T>
T* only_if_int( std::true_type is_int )
{
// code for T is int.
// pass other variables that need to be changed/read above
}
T* only_if_int( std::false_type ) {return nullptr;}
template<typename T>
T* only_if_char( std::true_type is_char )
{
// code for T is char.
// pass other variables that need to be changed/read above
}
T* only_if_char( std::false_type ) {return nullptr;}
template<typename T> T* function()
{
T* retval = only_if_int( std::is_same<T, int>() );
if (retval) return retval;
retval = only_if_char( std::is_same<T, char>() );
return retval;
}
template<class T>
T Add(T n1, T n2)
{
T result;
result = n1 + n2;
return result;
}
For In detail understanding of template, go through the below link:
http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part-1
you can define overloaded functions something like this:
#define INTT 0
#define CHARR 1
template<typename T>
T* function()
{
int type;
type = findtype(T);
//do remaining things based on the return type
}
int findType(int a)
{
return INTT;
}
int findType(char a)
{
return CHARR;
}
In the following code, initialize() illustrates a method based on compile-time polymorphism. The version of initialize() compiled depends on int2type<true> and int2type<false>, only one of which will be true for a given template parameter T.
It just so happens that data member T* m_datum; will work for both int2type<true> and int2type<false>.
Now, I want to change the int2type<false> version to std::vector<T> m_datum;, so my question is, how do I modify my code so that the data member m_datum is polymorphic on int2type<>?
Note: please ignore the rationale behind the code below - instead, I would like to focus on the mechanics of achieving compile-time polymorphism for data members.
#include <type_traits>
#include <stdlib.h>
using namespace std;
template <bool n>
struct int2type
{
enum { value = n };
};
template< typename T >
struct is_trivially_copyable
{
static const bool value = std::is_standard_layout<T>::value;
};
template<class T>
class Foo
{
public:
Foo( size_t n ) : m_nr( n )
{
initialize( int2type<is_trivially_copyable<T>::value>() );
}
~Foo() { }
private:
void initialize( int2type<true> )
{
m_datum = (T*) calloc( sizeof(T), m_nr );
}
void initialize( int2type<false> )
{
m_datum = new T[m_nr];
}
private:
size_t m_nr;
T* m_datum; // ok for int2type<true>
// vector<T> m_datum; // want to change to this for int2type<false>
};
class Bar
{
public:
Bar() { }
virtual ~Bar() { }
};
int main(int argc, char** argv)
{
Foo<int> foo_trivial( 5 );
Foo<Bar> foo_nontrivial( 10 );
return 0;
}
C++11 solution, based on Nawaz's recommendations
#include <type_traits>
#include <vector>
#include <stdlib.h>
using namespace std;
template< typename T >
struct is_trivially_copyable
{
static const bool value = std::is_standard_layout<T>::value;
};
template<class T>
class Foo
{
private:
static const bool what = is_trivially_copyable<T>::value;
typedef typename std::conditional<what,T*,std::vector<T>>::type type;
public:
Foo( size_t n ) : m_nr( n )
{
initialize( m_datum );
}
~Foo() { }
private:
void initialize( T* dummy )
{
m_datum = (T*) calloc( sizeof(T), m_nr );
}
void initialize( std::vector<T>& dummy )
{
m_datum.resize( m_nr );
}
private:
size_t m_nr;
type m_datum;
};
class Bar
{
public:
Bar() { }
virtual ~Bar() { }
};
int main(int argc, char** argv)
{
Foo<int> foo_trivial( 5 );
Foo<Bar> foo_nontrivial( 10 );
return 0;
}
C++11 Solution
Use std::conditional as:
#include <type_traits>
template<class T>
class Foo
{
//some info we can use throughout the class
static const bool what = is_trivially_copyable<T>::value;
typedef typename std::conditional<what, T*, std::vector<T>>::type data_type;
//data members
data_type m_data; //this is what you need!
}
C++03 Solution
You can write a metafunction and partially specialize this as follows:
template<class T>
class Foo
{
//primary template
template<bool b, typename T>
struct get { typedef T* type; };
//partial specialization
template<typename T>
struct get<false, T> { typedef std::vector<T> type; };
//some info we can use throughout the class
static const bool what = is_trivially_copyable<T>::value;
typedef typename get<what, T>::type data_type;
//data members
data_type m_data; //this is what you need!
};
So when what is true, data_type will turn out to be T*, or else it will be std::vector<T>, as desired.
In either case, you don't need int2type class template. Just remove that from your code. You can write cleaner code, without it.
How about:
// Generic
template <typename T, typename Arg>
struct datum_type_dispatch {};
// Specialization for Arg = int2type<true>
template <typename T>
struct datum_type_dispatch<T, int2type<true> >
{
typedef T* type;
};
// Specialization for Arg = int2type<false>
template <typename T>
struct datum_type_dispatch<T, int2type<false> >
{
typedef std::vector<T> type;
};
template <typename T>
class Foo
{
// ...
private:
// Get the datum type based on int2type<...>
typedef typename datum_type_dispatch<T, int2type<is_trivially_copyable<T>::value> >::type datum_type;
datum_type m_datum;
};