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.
Related
I'm currently implementing a dataset helper class template storing floating point values (Scalar) in a dynamically sized Eigen::Matrix constructed from a vector of different values types (Element) additionally storing a reference to this input vector. Now i want to partially specialize the constructor in the vector value type remaining a template in the scalar type to be explicitly instantiated.
Unfortunately i'm getting "unable to match function definition to an existing declaration" on VS 2010. The code is as simple as:
template <class Scalar, class Element> struct DataSet
{
DataSet(std::vector<Element> const & source);
// several generic member functions here ...
Eigen::Matrix<Scalar, ... > data;
std::vector<Element> const & source;
};
template<class Scalar>
DataSet<Scalar, SomeClass>::DataSet(std::vector<SomeClass> const & input)
{
// special impl for Element==SomeClass ...
}
SomeClass should be automatically be figured out by the compiler, when done right but i tried all meaningful combinations but still getting:
*.cpp(79) C2244 : unable to match function definition to an existing declaration
see declaration of 'DataSet<Scalar, Element>::DataSet'
I was not able to find a matching example by searching the internet yet. Thanks in advance!
EDIT:
To make it more specific, in my real world case i want to be able to define several partial specializations to the constructor with different types for Element e.g:
template<Scalar>
DataSet<Scalar, FirstClass>::DataSet(std::vector<FirstClass> const & first)
: data()
, source(first)
{
// special impl here ...
}
template<Scalar>
DataSet<Scalar, std::shared_ptr<SecondClass> >::DataSet(std::vector<std::shared_ptr<SecondClass> > const & second)
: data()
, source(second)
{
// special impl here ...
}
Redeclaring/specializing the class completely to a certain typename is not desired. Then there is little use to be a template at all. I want the solution as it is, otherwise there might be other strategies to my problem.
FIN:
Since it looks like not being possible to share the type Element between class template and constructor by only specializing the constructor (which is somehow related to an implicit specialization of the class) i removed the reference source from the class template entirely and copied the needed information into a generic container and implemented the constructors via overloads.
When defining your constructor, you didn't explicitly provide both template arguments for its class. That would need to be revised as follows:
template<typename T_Scalar, typename T_Element>
DataSet<T_Scalar, T_Element> // template args for type
::DataSet(std::vector<T_Element> const &input) // but none for constructor
{
// stuff
}
Tangentially related: Unlike methods, template arguments for classes cannot be deduced from constructor calls. That is: until C++17 comes around! woo!
The next stumbling block you faced is that template specialisations do not 'inherit' members from their primary template. It is somewhat intuitive to assume they would, but it's just not so. Until I find an official rationale, I presume it's because template arguments might make certain members totally inapplicable to a specialisation, rendering implicit 'inheritance' problematic. If so, it would've been decided to require full redeclaration / not judged worthwhile to add arcane syntax to specify which primary 'base' members are 'inherited'... when you can simply use real inheritance to ensure they are.
Anyway, what that means is that to get a partial specialisation, you need to declare the whole thing - in this case, the class and its constructor - before you can specialise that constructor's definition. You hadn't declared these ahead of time, so the compiler rightly complained that it couldn't see a declaration.
// Define specialised class
template<typename T_Scalar>
class DataSet<T_Scalar, SomeClass>
{
public:
// Declare its ctor
DataSet(std::vector<SomeClass> const &);
}
// Implement its ctor
template<typename T_Scalar>
DataSet<T_Scalar, SomeClass> // complete template args
::DataSet(std::vector<SomeClass> const &input)
{
// stuff
}
See my working example of an equivalent template class, showing general vs. specialised instantiations.
To add to your original confusion, which is fair! - note that out-of-line definitions can get very complicated indeed if a template class itself contains a template function, because then you need 2 template clauses, e.g.
template<typename TA, typename TB>
class Widget {
template<typename TC>
void accept_gadget(TC &&gadget);
};
template<typename TA, typename TB>
template<typename TC>
Widget<TA, TB>
::accept_gadget(TC &&gadget)
{
/* ... */
}
Something that will help a lot in many contexts, especially including such out-of-line template definitions, is if the proposal to allow namespace class is accepted in a future version. Very sad this didn't make it into C++17... and very odd that it was ever missing in the 1st place!
According to ยง14.7.3.16:
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
Still, you can use std::enable_if to partial-specialize your contructor:
template <class Scalar, class Element> struct DataSet
{
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<!std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "Element\n";
}
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "SomeClass\n";
}
};
But this way is restrictive:
all your conditions must be exclusives
you'll have to modify the code of your class for every new class you want to handle.
Instead, I'd advise you to use a template helper structure:
DataSet(std::vector<Element> const & input) {
Helper<Element>::do_it(input);
}
that you can specialize as you want:
template <class Element>
struct Helper {
static void do_it(std::vector<Element> const & input) {
std::cout << "General form with Element\n";
}
};
template<>
struct Helper<SomeClass> {
static void do_it(std::vector<SomeClass> const & input) {
std::cout << "SomeClass\n";
}
};
template<>
struct Helper<SomeOtherClass> {
static void do_it(std::vector<SomeOtherClass> const & input) {
std::cout << "SomeOtherClass\n";
}
};
...
I would like to define a nullary static template member function which would be (explicitly) specialized on pointer-to-data-member and could have, for each specialization, different return type.
It should return some detailed information about each attribute, hence I will call this method trait. The trait object type returned will be inspected by other templates, so this whole machinery must be available at compile-time.
So far I have something like this (broken code, of course):
class Foo{
// some data members
int a; std::string b; int c;
// how to declare generic template here?
// compile-time error should ensue if none of the specializations below is matched
// specialization for a (aTraitExpr is expanded from macro, so it is OK to repeat it)
template auto trait<&Foo::a>()->decltype(aTraitExpr){ return aTraitExpr; }
// specialization for b; the return type will be different than for trait<&Foo::a>
template auto trait<&Foo::b>()->decltype(bTraitExpr){ return bTraitExpr; }
};
// some code which queries the trait at compile-time
// e.g. supposing all possible trait types declare isSerializable
// which happens to be True for a and False for b
Foo* foo;
template<bool isSerializable> void doSerialization(...);
template void doSerialization<true>(...){ ... };
template void doSerialization<false>(...){ /* no-op */ };
doSerialization<Foo::trait<&Foo::a>()::isSerializable>(...); // -> doSerialization<true>(foo)
doSerialization<Foo::trait<&Foo::b>()::isSerializable>(...); // -> doSerialization<False>(...)
doSerialization<Foo::trait<&Foo::c>()::isSerializable>(...); // -> compile error, specialization Foo::trait<&Foo::c> not defined
Could get some hint on how to achieve this? (I am not trying to invent a new serialization system, I already use boost::serialization; there will be more information in each trait, this is just for an example why it is needed at compile-time).
EDIT: I was able to get something nearing what I want, it is shown at ideone.com. I gave up having trait<Foo::a>() (for now), so there is static function getTrait_a() which returns reference to modifiable type-traits, which are however partially fixed at compile-time (so that Foo::TraitType_a::flags works, for instance). Thanks to everybody who replied, unfortunately I can only pick one of the answers as "answer".
It looks like you want several overloads instead of specializations. Unfortunately you don't detail on what xTraitExpr is, but it seems it's just a type that has a member isSerializable defined. I would probably go like this
class Foo {
// your members have been omitted to save space...
template<typename T, T Foo::*M>
struct W { };
static decltype(aTraitExpr) trait(W<int, &Foo::a>) {
return aTraitExpr;
}
static decltype(bTraitExpr) trait(W<std::string, &Foo::b>) {
return bTraitExpr;
}
// other overloads for other members...
public:
// overloads for each member type
template<int Foo::*M>
static decltype(trait(W<int, M>())) trait() {
return trait(W<int, M>());
}
template<std::string Foo::*M>
static decltype(trait(W<std::string, M>())) trait() {
return trait(W<std::string, M>());
}
};
trait(W<M>()) is a dependent call. A dependent call does ADL at definition and instantiation time and unqualified lookup only at definition time. That's why W and the additional trait overloads using it must be defined before the trait type overloads instead of after them, or the result of resolution in the return type and body of the functions will be different since they are parsed at different times (bodies are late parsed after the class definition, and return types are parsed immediately).
You can either make trait a constexpr function and make xTraitExpr be a literal class with a constexpr constructor initializing isSerializable appropriately, or you could apply decltype as follows
doSerialization<decltype(Foo::trait<&Foo::a>())::isSerializable>(...);
I think it doesn't make sense to use a function template here. That being said, using a class template in its stead isn't that convenient either: you have to account for the fact that the non-static data members can have different types and there can be several non-static data members with the same type. Here's a possibility:
template<typename T>
struct is_serializable: std::false_type {};
struct Foo {
int a; std::string b; int c;
// Primary template left undefined on purpose
// alternatively, could use a static_assert on a dependent
// std::false_type::value for better diagnostics
template<typename T, T t>
struct attribute_trait;
};
// Define explicit specializations outside of class
template<>
struct Foo::attribute_trait<int Foo::*, &Foo::a>
: is_serializable<int> {};
template<>
struct Foo::attribute_trait<std::string Foo::*, &Foo::b>
: is_serializable<std::string> {};
Which is usable as
doSerialization<Foo::attribute_trait<decltype(&Foo::a), &Foo::a>::value>(/* stuff */);
The usual way to define a traits class is by wrapping a struct/class around a compile-time constant expression (and not by wrapping a function returning such an expression). The syntax to take a class member function is like this:
template
<
SomeReturnType (SomeClass::*SomeMemberFunction)(SomeParameters)
>
class SomeTrait
{
static const value = SomeCompileTimeConstantExpression;
};
In your case, you would do it like that:
template
<
void (Foo::*f)()
>
class trait
{
static const value = fTraitExpr;
};
You then specialize this trait for all member functions of class Foo:
template<>
class trait<&Foo::a>
{
static const value = aTraitExpr;
};
// same for Foo::b and Foo::c
Furthermore, it is more idiomatic to overload function templates than to specialize them:
template<int V> struct Int2Type { enum { value = V }; };
Foo* foo;
template
<
void (Foo::*f)()
>
void doSerialization(...)
{
dispatch::doSerialization(Int2Type< trait<f>::value >(), ...);
}
namespace dispatch {
doSerialization(Int2Type< true >, ...) { ... };
doSerialization(Int2Type< false >, ...) { /* no-op */ };
} // namespace dispatch
You can then call it like this:
doSerialization<&Foo::a>(...);
doSerialization<&Foo::b>(...);
doSerialization<&Foo::c>(...);
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? :)
I want to detect existence of a specific member function for a class, using the usual SFINAE trick.
template<typename T>
struct has_alloc
{
template<typename U,U x>
struct dummy;
template<typename U>
static char test(dummy<void* (U::*)(std::size_t),&U::allocate>*);
template<typename U>
static char (&test(...))[2];
static bool const value = sizeof(test<T>(0)) ==1;
};
It should be noted that this detects a different kind of allocator which has void* allocate(std::size_t) as member function which are non standard (probably some raw memory allocator).
Next, I have an incomplete type and an std::allocator for that incomplete type.
struct test;
typedef std::allocator<test> test_alloc;
And I am checking whether the test_alloc is the one I am looking for.
struct kind_of_alloc
{
const static bool value = has_alloc<test_alloc>::value;
};
Surely struct test will be complete when I will "use" test_alloc such as
#include "test_def.hpp"//contains the code posted above
struct test{};
void use()
{
test_alloc a;
}
in another compilation unit. However when the has_alloc test happens,the compiler tries to instantiate the allocate function for std::allocator and finds that sizeof an incomplete type is used inside function body, and causes a hard error.
It seems that the error doesn't occur if the implementation of allocate separated and included separately at the point of use such as
template<typename T>
T* alloc<T>::allocate(std::size_t n)
{
return (T*)operator new(sizeof(T)*n);
}
void use()
{
test_alloc a;
a.allocate(2);
}
And test_def.hpp contains
template<typename T>
struct alloc
{
T* allocate(std::size_t n);
};
However while I can do this for alloc<T> , it is not possible for std::allocator as separating out the implementation is not possible.
What I am looking for is it possible to test whether a function with void* allocate(size_t) exists in test_alloc. If not, it will test negative, and if yes ,i.e. if the function signature matches, even if it can not be instantiated there, test positive.
No, SFINAE is only in effect during overload resolution. Once a resolution has been made and the compiler begins instantiating the function SFINAE is over.
Edit: and taking the address of a function instantiates it.
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.