I have a templated class that has a data member of type std::vector<T>, where T is also a parameter of my templated class.
In my template class I have quite some logic that does this:
T &value = m_vector[index];
This doesn't seem to compile when T is a boolean, because the [] operator of std::vector does not return a bool-reference, but a different type.
Some alternatives (although I don't like any of them):
tell my users that they must not use bool as template parameter
have a specialization of my class for bool (but this requires some code duplication)
Isn't there a way to tell std::vector not to specialize for bool?
You simply cannot have templated code behave regularly for T equal to bool if your data is represented by std::vector<bool> because this is not a container. As pointed out by #Mark Ransom, you could use std::vector<char> instead, e.g. through a trait like this
template<typename T> struct vector_trait { typedef std::vector<T> type; };
template<> struct vector_trait<bool> { typedef std::vector<char> type; };
and then use typename vector_trait<T>::type wherever you currently use std::vector<T>. The disadvantage here is that you need to use casts to convert from char to bool.
An alternative as suggested in your own answer is to write a wrapper with implicit conversion and constructor
template<typename T>
class wrapper
{
public:
wrapper() : value_(T()) {}
/* explicit */ wrapper(T const& t): value_(t) {}
/* explicit */ operator T() { return value_; }
private:
T value_;
};
and use std::vector< wrapper<bool> > everywhere without ever having to cast. However, there are also disadvantages to this because standard conversion sequences containing real bool parameters behave differently than the user-defined conversions with wrapper<bool> (the compiler can at most use 1 user-defined conversion, and as many standard conversions as necessary). This means that template code with function overloading can subtly break. You could uncomment the explicit keywords in the code above but that introduces the verbosity again.
Use std::vector<char> instead.
Would the following work for you?
template <typename T>
struct anything_but_bool {
typedef T type;
};
template <>
struct anything_but_bool<bool> {
typedef char type;
};
template <typename T>
class your_class {
std::vector<typename anything_but_bool<T>::type> member;
};
Less flippantly, the name anything_but_bool should probably be prevent_bool or similar.
I found an even more elegant solution, based on all of your input.
First I define a simple class that holds one member. Let's call this wrapperClass:
template <typename T>
class wrapperClass
{
public:
wrapperClass() {}
wrapperClass(const T&value) : m_value(value) {}
T m_value;
};
Now I can define my std::vector in my templated class like this:
std::vector<wrapperClass<T>> m_internalVector;
Since sizeof(WrapperClass<bool>) is also 1, I expect that sizeof(WrapperClass<T>) will always be equal to sizeof(T). Since the data type is now not a bool anymore, the specialization is not performed.
In places where I now get an element from the vector, I simply replace
m_internalVector[index]
by
m_internalVector[index].m_value
But this seems much more elegant than using traits to replace bool by char, and then using casts to convert between char and bool (and probably reinterpret casts to convert char& to bool&).
What do you think?
You could use a custom proxy class to hold the bools.
class Bool
{
public:
Bool() = default;
Bool(bool in) : value(in) {}
Bool& operator=(bool in) {value = in;}
operator bool() const& {return value;}
private:
bool value;
};
This might require a bit of tweaking for your purposes, but it's usually what I do in these cases.
std::basic_string<bool> flags(flagCount, false);
Semantically, using string is weird, but it works basically like std::vector, behaves as expected with pointers/references, and it conveniently converts to std::span<bool> when passing to functions that take span, no need for wrapper classes or reinterpret_cast's (e.g. using std::vector<uint8_t> makes these cases awkward because of the casts). Until/unless C++ adds a std::bit_vector and deprecates the specialization, we don't have many good options.
There is a ways to prevent the vector<bool> specialization: Passing a custom allocator.
std::vector<bool, myallocator> realbool;
The following article has some details:
https://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98
Of course, this requires that you have control over the vector definitions, so it's probably not really a solution for you. Apart from that, it also has some downsides of it's own...
Related
I'm stuck with c++17 for a project, so I don't have access to designated initializers. I have a bunch of union types that I want to avoid initializing this way (because it is annoying):
MyUnionType x;
x.value = value_set_for_all_union_members;
I want to instead have this
MyUnionType x(value_set_for_all_union_members);
But I also want to avoid writing an implementation for each union I create. I know that all my union types are going to be of the following structure, each union is meant to actually represent bit a bit field, so I actually do want type pruning here, I know it is "UB" according to C++, but that is on the C++ committee, in C it is not undefined behavior, and thus all compilers that I care about will do what I want here.
union Example{
integer_type value;
custom_safe_bitfield_abstraction<...> a;
custom_safe_bitfield_abstraction<...> b;
...
};
I thought, okay, I'll just inherit the constructor, and use CRTP to extract the appropriate integer_type. Of course I can't inherit on a union directly, so instead I opted for this strategy:
struct Example : Base<Example>{
union{
integer_type value;
custom_safe_bitfield_abstraction<...> a;
custom_safe_bitfield_abstraction<...> b;
...
};
};
using an anonymous union, I should be able to use it the same exact way as before (example.value should be the value inside of union).
Then in the implementation I do the following:
template<class Derived_T>
struct Base{
using value_type = decltype(Derived_T::value);
explicit Base(value_type v){
static_cast<Derived_T*>(this)->value = v;
}
}
This however doesn't work:
error: Incomplete type 'Example' used in nested name specifier
> using value_type = decltype(Derived_T::value);
Apparently we aren't allowed to refer to a member before it has been declared. Okay... but there must be some way to extract the type data out, after all I don't care about any memory alignment or anything.
The only other thing I can think of, is include the type in the CRTP template parameter (ie Base<Derived_T, value_type>) but I want to avoid doing that. I imagine there is some method for writing a function or specifying an internal type on each derived class, I don't want to do that either (and sort of defeats the purpose of what I'm doing anyway).
Is there a way to avoid writing the constructor per class, and with out sacrificing the other code duplication minimization goals I have?
Not exactly what you asked... but you can use the fact that you can use the type of D::value inside a member function... so using SFINAE over a template contructor...
I mean, you can write something as
template <typename D>
struct Base
{
template <typename T>
static constexpr bool is_value_type ()
{ return std::is_same_v<decltype(D::value), T>; }
template <typename T, bool B = is_value_type<T>(),
std::enable_if_t<B, int> = 0>
explicit Base (T v)
{ static_cast<D*>(this)->value = v; }
};
where the template constructor is enabled only if the deduced type of the argument is of the same type of B::value.
Remember also to add the using
using Base<Example>::Base;
inside Example.
The following is a full compiling example
#include <type_traits>
template <typename D>
struct Base
{
template <typename T>
static constexpr bool is_value_type ()
{ return std::is_same_v<decltype(D::value), T>; }
template <typename T, bool B = is_value_type<T>(),
std::enable_if_t<B, int> = 0>
explicit Base (T v)
{ static_cast<D*>(this)->value = v; }
};
struct Example : Base<Example>
{
using Base<Example>::Base;
union
{
long value;
long a;
long b;
};
};
int main ()
{
//Example e0{0}; // compilation error
Example e1{1l}; // compile
//Example e2{2ll}; // compilation error
}
I'm building a datastructure class with an std-like interface, and implementing different iterators for the data structure.
Conceptually, what I would like to do is something like this:
template <class DataT>
class DataStructure
{
protected:
DataT& Data;
public:
DataStructure(DataT& data) : Data(data) {}
class BaseIterator
{
public:
BaseIterator()
{
cout<<"BaseIterator"<<endl;
}
};
class DerrivedIterator1 : public BaseIterator
{
public:
DerrivedIterator1()
{
cout<<"DerrivedIterator1"<<endl;
}
};
class DerrivedIterator2 : public BaseIterator
{
public:
DerrivedIterator2()
{
cout<<"DerrivedIterator2"<<endl;
}
};
template<class IterT>
IterT Begin()
{
//none-specialized implementation. Possibly throw exception
}
template<>
DerrivedIterator1 Begin<DerrivedIterator1>()
{
//Find beginning for DerrivedIterator1
}
template<>
DerrivedIterator2 Begin<DerrivedIterator2>()
{
//Find beginning for DerrivedIterator1
}
};
But this of course does not compile since C++ doesn't allow to specialize template member functions in none-specialized template containers.
The obvious workaround is of course to declare 2 different functions: Begin_Iterator1 and Begin_Iterator2 and be done with it. But I'm looking for a workaround that doesn't change the interface.
Any ideas?
Edit: I forgot to mention that this is for a HW assignment and so boost and even std is not an option.
Function templates cannot be specialized in C++, point.
It does not matter whether they are members of template or not, specialization of function templates is not allowed. Normally when using argument types to infer the template arguments, overloading does the same specialization would, so specialization for functions (and the associated extra complexity in overload resolution and such) was not deemed necessary.
You however don't have any arguments to infer on and would instantiate the templates manually. No,
DataStructure::DerivedIterator1 i = dataStructure.Begin();
would not work as you wrote the code, because type inference, just like overload resolution is only done on the arguments, not expected return value. You'd have to write:
DataStructure::DerivedIterator1 i = dataStructure.Begin<DataStructure::DerivedIterator1>();
and that has zero benefit over:
DataStructure::DerivedIterator1 i = dataStructure.BeginIterator1();
However, the first expression can be made to work with some wizardry. First you have to define BeginIterator1 and BeginIterator2 and than you'd do a temporary to late-decide which one to construct:
class DataStructure {
...
class BeginIteratorConstructor {
DataStructure &dataStructure;
public:
BeginIteratorConstructor(DataStructure &ds) : dataStructure(ds) {}
operator DerivedIterator1() { return dataStructure.BeginIterator1(); }
operator DerivedIterator2() { return dataStructure.BeginIterator2(); }
};
BeginIteratorConstructor Begin() { return BeginIteratorConstructor(*this); }
...
};
Now dataStructure.Begin() will return a temporary something, that will call BeginIterator1 if you cast it to DerivedIterator1 or call BeginIterator2 when you cast it to DerivedIterator2. If you pass it to something where the compiler can't decide which one to cast to, it will die either because of ambiguous overload or because BeginIteratorConstructor is not in fact iterator and you'll have to cast it explicitly.
(You should carefully make as much of the BeginIteratorConstructor private, but I am not sure how far will the compiler allow you to go, so you'd have to experiment a bit)
You can use a tagging system, which will save you from partially specialized functions inside class templates:
struct base_iter_tag{};
struct der1_iter_tag{};
struct der2_iter_tag{};
template<class T>
struct iter_type;
template<>
struct iter_type<BaseIterator>{
typedef base_iter_tag tag;
};
template<>
struct iter_type<DerivedIterator1>{
typedef der1_iter_tag tag;
};
template<>
struct iter_type<DerivedIterator2>{
typedef der2_iter_tag tag;
};
template<class IterT>
IterT Begin(){
return DoBegin(typename iter_type<IterT>::tag());
}
BaseIterator DoBegin(base_iter_tag){
// ...
}
DerivedIterator1 DoBegin(der1_iter_tag){
// ...
}
DerivedIterator2 DoBegin(der2_iter_tag){
// ...
}
This is essentially what the standard library does with the iterator_traits<T>::iterator_category and overloaded functions depending on the category (e.g. forward_iterator_tag, random_access_iterator_tag, etc...).
I have a template function that I expect to be templatized for different types at different places.
The problem is that I would like to know at compile time if there is an specialization for the given type to generate in 2 different ways another template.
template<typename T>
bool tobool(const T&){ throw Exception("Can't cast to bool");};
template<> bool tobool<bool>(const bool &value){ return value;}
I know you can test for function existance like in here.
Any chance on how to test if tobool has been specialized?
Imagine that I want to generate a isbool() that returns true if tobool() has been specialized and returns false if not.
As a (somewhat ugly and brittle) workaround, you could require specialization of a struct rather than a function and include a class constant to indicate whether the struct has been specialized:
template <typename T>
struct ToBool {
static bool tobool(const T&);
static const bool specialized = false;
};
Another option is to only define tobool in specializations. That way, ToBool<Foo>::tobool(f) won't compile for any classes Foo that ToBool hasn't been specialized for.
As an alternative to tobool, you can use explicit conversion operators if you have control over the classes to be converted.
class Foo {
public:
operator bool();
...
};
...
Foo f;
if (f) ...
If the type doesn't have a bool conversion (well, a conversion to a numeric or pointer type, both of which have standard conversions to bool), the program won't compile. Voila, compile time checking for a conversion.
If you don't want implicit conversion to bool, you can define an operator! and use a double-bang for explicit conversion (though this isn't as readable):
class Foo {
public:
bool operator!();
...
};
...
Foo f;
if (!!f) ...
The answer to your specific question is this: No, you cannot check whether T is using the primary or the specialized template. #Martin York's question is a very good one: why on earth would you want to check that? :)
In < Modern C++ Design >,it introduces a way to check if a type fundamental type by introducing the so called type list. but what if I don't want to include so many loki code and just want a simple function to implement that? What is the simplest way to do that?
don't re-invent the wheel use boost::type_traits
http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/index.html
You can use template specialization to get what you want.
// General template
template<typename T>
struct IsFundamentalType { enum { result = false }; };
// Template specializations for each fundamental type
template<>
struct IsFundamentalType<char> { enum { result = true }; };
template<>
struct IsFundamentalType<int> { enum { result = true }; };
template<>
struct IsFundamentalType<short> { enum { result = true }; };
template<>
struct IsFundamentalType<float> { enum { result = true }; };
// And so on for other fundamental types ...
class NonFundamentalType
{
};
template<typename T>
void DoSomething(const T& var)
{
if(IsFundamentalType<T>::result)
{
printf("I'm fundamental type!\n");
}
else
{
printf("I'm not a fundamental type!\n");
}
}
int main()
{
int i = 42;
char c = 42;
short s = 42;
float f = 42.0f;
NonFundamentalType nft;
DoSomething(i);
DoSomething(c);
DoSomething(s);
DoSomething(f);
DoSomething(nft);
}
In this code, if you pass in a type such as int or char, the compiler will use the specialization of IsFundamentalType (given that you've defined the specializations for all fundamental types). Otherwise, the compiler will use the general template, as it is the case for the NonFundamentalType class. The important thing is that the specialized ones have a result member defined as true, while the general template also has a result member defined as false. You can then use the result member for the if statement. Optimizing compilers should be able to elide the if statement seeing that the expression reduces to a constant true/false value, so doing something like this should not impose a runtime penalty.
The simplest way is to create a type-traits object. Basically, you create an object (let's call it is_fundamental<T>) that is parameterized by the type and that inherits from boost::type_traits::no_type by default; then you specialize the object on all the fundamental types, making that specialization inherit from boost::type_traits::yes_type. So then you can use is_fundamental<T>::value as a boolean which will tell you if the type T is or is not a fundamental type. In most cases, you really don't need to know if a type is or is not fundamental, and when you do, it almost always involves templates, anyway, so might as well do it that way.
I should also point out that Boost already defines boost::type_traits::is_fundamental which does what you want. You can see in is_fundamental.hpp that they define it in terms of their other type-traits objects; a type is fundamental if it is a builtin arithmetic type or if it is the type "void" (which is also considered to be fundamental). Trying to figure things out from Boost can be kind of confusing but a simplification is:
template<typename T, T VAL> struct constant_value
{
static const T value = VAL;
};
typedef constant_value<bool,true> yes_type;
typedef constant_value<bool,false> no_type;
template<typename T> struct is_fundamental : public no_type{};
// Create a macro for convenience
#define DECLARE_FUNDAMENTAL(X) \
template<> struct is_fundamental<X> : public yes_type{}
// Specialize for all fundamental types
DECLARE_FUNDAMENTAL(void);
DECLARE_FUNDAMENTAL(bool);
DECLARE_FUNDAMENTAL(signed char);
DECLARE_FUNDAMENTAL(unsigned char);
// ... lots more similar specializations ...
DECLARE_FUNDAMENTAL(wchar_t);
DECLARE_FUNDAMENTAL(float);
DECLARE_FUNDAMENTAL(double);
DECLARE_FUNDAMENTAL(long double);
// Prevent this macro from polluting everything else...
#undef DECLARE_FUNDAMENTAL
That is essentially what it takes to create such a type-traits object. Note that one can maliciously specialize the type-trait to be true for a non-fundamental type, although that is the case for most things, anyway.
You can then use the above to create a more function-looking thing. For example, using the boost::type_traits::is_fundamental class, you could create the following:
template<typename T>
bool isFundametal(const T&)
{
return boost::type_traits::is_fundamental<T>::value;
}
Because the template specialization can be deduced from the parameters, you can invoke this isFundamental function without explicitly specifying the type. For example, if you write isFundamental(5) it will implicitly invoke isFundamental<int>(5), which will return true. Note, though, that if you create such a function, it won't allow you to test for void. You could create a function that took no parameters for such a case, but then the type wouldn't be deduced, and so it would be no prettier than simply using boost::type_traits::is_fundamenta<T>::value, and so one might as well just use it in that case.
I was reading the STL source code (which turned out to be both fun and very useful), and I came across this kind of thing
//file backwards/auto_ptr.h, but also found on many others.
template<typename _Tp>
class auto_ptr
//Question is about this:
template<>
class auto_ptr<void>
Is the template<> part added to avoid class duplication?
That's specialization. For example:
template <typename T>
struct is_void
{
static const bool value = false;
};
This template would have is_void<T>::value as false for any type, which is obviously incorrect. What you can do is use this syntax to say "I'm filling in T myself, and specializing":
template <> // I'm gonna make a type specifically
struct is_void<void> // and that type is void
{
static const bool value = true; // and now I can change it however I want
};
Now is_void<T>::value is false except when T is void. Then the compiler chooses the more specialized version, and we get true.
So, in your case, it has a generic implementation of auto_ptr. But that implementation has a problem with void. Specifically, it cannot be dereferenced, since it has no type associated with it.
So what we can do is specialize the void variant of auto_ptr to remove those functions.