consider the code
template <class A>
class B;
template <class A>
class B<const A>{};
template <class A, int N>
class B<A[N]>{};
template <class A>
class B<A*>{};
template <class A>
class B<A&>{};
The following template instantiations work fine:
A<int*&>
A<const int*>
A<int*[3]>
but the following one doesn't work:
A<const int[3]>
Is there some reason that this particular combination is invalid or is it perhaps a bug with g++4.6.3?
By the way I managed to get around this using SFINAE and boost::disable_if<>, so at least the problem is solved.
EDIT
I forgot to mention that the error in question is an ambiguous class template instantiation and it couldn't decide between the overload for const or the overload for an array.
EDIT2
This has nothing to do with pointers, here's the full context:
I'm going through the book C++ Template Metaprogramming and am doing question 2-3 (Chapter 2 question 3) which says:
Use the type traits facilities to implement a type_descriptor class template, whose instances, when streamed, print the type of their template parameters:
NOTE: we cannot use RTTI to the same effect since, according to 18.5.1 [lib.type.info] paragraph 7 of the standard, typeid(T).name() is not guaranteed to return a meaningful result.
My solution (including the the workaround for the compilation error) is as follows:
//QUESTION 2-3
template <class T, class enable = void>
struct type_descriptor
{
std::string operator()() const
{
return "Unknown";
}
};
//specializations for primitive types
#define TYPE_DESC_SPEC(type) template <> \
struct type_descriptor<type,void> \
{std::string operator()() const{return #type;}};
TYPE_DESC_SPEC(int)
TYPE_DESC_SPEC(long)
TYPE_DESC_SPEC(void)
TYPE_DESC_SPEC(short)
TYPE_DESC_SPEC(unsigned char)
TYPE_DESC_SPEC(unsigned short)
TYPE_DESC_SPEC(unsigned long)
//specializations for modifiers *, const, &, and [N]
template <class T>
struct type_descriptor<T&,void>
{std::string operator()(){return type_descriptor<T>()() + " &";}};
template <class T>
struct type_descriptor<T*,void>
{std::string operator()(){return type_descriptor<T>()() + " *";}};
//Replace void with what's in the comment for the workaround.
template <class T>
struct type_descriptor<const T, void/*typename boost::disable_if<boost::is_array<T> >::type*/>
{std::string operator()(){return type_descriptor<T>()() + " const";}};
template <class T>
struct type_descriptor<T(*)(),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)()";}};
template <class T, class U>
struct type_descriptor<T(*)(U),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)(" + type_descriptor<U>()() + ")";}};
template <class T, int N>
struct type_descriptor<T[N],void>
{
std::string operator()()
{
std::stringstream s;
s << type_descriptor<T>()() << " [" << N << "]";
return s.str();
}
};
template <class T>
struct type_descriptor<T[],void>
{std::string operator()(){return type_descriptor<T>()() + " []";}};
//Now overload operator<< to allow streaming of this class directly
template <class T>
std::ostream & operator<<(std::ostream & s, type_descriptor<T> t)
{
return s << t();
}
//END QUESTION 2-3
Sample usage is:
std::cout << "\nQuestion 2-3 results\n";
std::cout << type_descriptor<int*>() << std::endl;
std::cout << type_descriptor<int*[3]>() << std::endl;
std::cout << type_descriptor<std::string*>() << std::endl;
std::cout << type_descriptor<const int&>() << std::endl;
std::cout << type_descriptor<const int *const&>() << std::endl;
std::cout << type_descriptor<int[4]>() << std::endl;
std::cout << type_descriptor<int(*)()>() << std::endl;
std::cout << type_descriptor<int*&(*)(const char &)>() << std::endl;
std::cout << type_descriptor<int*&>() << std::endl;
std::cout << type_descriptor<int[]>() << std::endl;
std::cout << type_descriptor<const long[]>() << std::endl;
and the corresponding output is (when the workaround is in, otherwise it doesn't compile on that last one):
int *
int * [3]
Unknown *
int const &
int const * const &
int [4]
int (*)()
int * & (*)(Unknown const &)
int * &
int []
long const []
So C++ is able to differentiate pointers and arrays for the template parameters, is able to correctly, recursively, separate compound types and output the correct result, except for const A[]. It needs help with that one
An array type with a const element type is both a const qualified type (the const applies bidirectionally) and an array type.
So you should fix the specializations.
Related
If you have a class template such as this:
template <typename T, unsigned CAPACITY>
class Collection
{
T m_array[CAPACITY]{};
T m_dummy{};
unsigned m_size{};
}
public:
void display(std::ostream& ostr = std::cout) const
{
ostr << "----------------------" << std::endl;
ostr << "| Collection Content |" << std::endl;
ostr << "----------------------" << std::endl;
}
And I wanted to create specialization depending on the type used, but not the CAPACITY, is this possible?
I have this, which works:
void Collection<Pair, 50u>::display(std::ostream& ostr) const
{
ostr << "----------------------" << std::endl;
ostr << "| This is a Pair |" << std::endl;
ostr << "----------------------" << std::endl;
}
When it is called as:
Collection<Pair, 50> colDictionary;
But this only works if the type is Pair, as well as the exact CAPACITY is 50.
This is what I had in mind, allowing for type to be Pair and CAPACITY to be anything:
void Collection<Pair>::display(std::ostream& ostr) const
{
ostr << "----------------------" << std::endl;
ostr << "| This is a Pair |" << std::endl;
ostr << "----------------------" << std::endl;
}
But this causes a "too few arguments for class template" error.
Any way to do this without changing the actual class template itself?
It's called a partial template specialization:
template <class T, unsigned Capacity>
struct Collection {
};
template <unsigned Capacity>
struct Collection<Pair, Capacity> {
// Specialize
};
One thing to note is that you cannot partially specialize a single function. You have to specialize the whole class template, which is irritating if the class template is long. Another quick-and-dirty way of doing this if you want to specialize a single function would be to just use a "compile-time if":
#include <type_traits>
template <class T, unsigned Capacity>
struct Collection {
void display() const {
if constexpr (std::is_same_v<T, Pair>) {
// pair implementation
} else {
// general implementation
}
}
};
Or, as a more clean solution, try moving the whole thing out of the class and add a simple overload:
// Free-standing overloads:
template <class T, unsigned Capacity>
void diplay(Collection<T, Capacity> const& c) { /* ... */ }
template <unsigned Capacity>
void display(Collection<Pair, Capacity> const& c) { /* ... */ }
// The member function delegates the work to
// the overloaded functions. No template specialization
// is involved:
template <class T, unsigned Capacity>
struct Capacity {
void display() const {
display(*this); // calls the correct overload.
}
};
It seems difficult to do a partial specification.
Some ways are helpful for you to achieve it:
Define a specification class for this type situation.
If you just only desire to custom this behavior(but not too much and it's limited), you can use if-constexpr branches.
If you want to avoid a class-partial-template (because it's a burden to rewrite all codes), then use a global function template is helpful.
Some suggested codes are given:
#include <iostream>
template <typename T, unsigned capacity>
class Collection {
public:
void display(std::ostream &ostr = std::cout) const;
};
template <typename T, unsigned c>
void Collection<T, c>::display(std::ostream &ostr) const {
if constexpr (c == 50u) {
ostr << "Specification! \n";
} else {
ostr << "Normal Realization. \n";
}
}
int main() {
Collection<int, 50> c;
c.display();
}
If you need to specialize a certain member function, you can use the Curiously Recurring Template Pattern (or CRTP for short). You'd then create a base class and a specialization of that base class. Both contain only the specific member function that you want to specialize.
template <class T, class CRTP, unsigned Capacity>
struct display_impl {
void display() const {
auto& This = static_cast<const CRTP&>(*this);
// Use `This` to access members of Collection
}
};
template <class CRTP, unsigned Capacity>
struct display_impl<Pair, CRTP, Capacity> {
void display() const {
auto& This = static_cast<const CRTP&>(*this);
// Use `This` to access members of Collection
}
};
Collection will now inherit from display_impl and supply itself as a template parameter:
template <class T, unsigned Capacity>
struct Collection : display_impl<T, Collection<T, Capacity>, Capacity> {
friend struct display_impl<T, Collection<T, Capacity>, Capacity>;
};
Demo
I'm trying to differentiate between user types and primitive types in a variadic template.
I have tried overloading binary operator, but that only says that there's no fitting overload for 'user types'...
template <typename T>
void PrintParams(T t)
{
if (IsAUserType)
std::cout << typeid(t).name();
else
std::cout << t;
}
template <typename First, typename... Rest>
void PrintParams(First first, Rest... rest)
{
if (IsAUserType)
std::cout << typeid(first).name();
else
std::cout << first;
PrintParams(rest...);
}
// If you know what to do with this, then that would also be very helpful...
//Overload << operator for user types
//template <typename T>
//friend std::ostream& operator<< (std::ostream& os, T t)
//{
//
//if (std::is_fundamental<t>::value)
//std::clog << t;
//else
//std::clog << typeid(t).name();
//}
expected result for input like (class test, 3.4, "string") would be
"test3.4string"
You could split your single argument function up in two and use SFINAE to enable the correct one depending on if the argument is a fundamental type or not:
template<typename T, typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0>
void PrintParams(T t) {
std::cout << t;
}
template<typename T, typename std::enable_if<!std::is_fundamental<T>::value, int>::type = 0>
void PrintParams(T t) {
std::cout << typeid(t).name();
}
template<typename First, typename... Rest>
void PrintParams(First first, Rest... rest) {
PrintParams(first); // ... and call the single argument version here
std::cout << ",";
PrintParams(rest...);
}
Another way would be to check if the type supports streaming using operator<< instead of checking that it's a fundamental type. That would make streaming work for classes (like std::string and user defined ones too).
#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <utility>
// SFINAE support
namespace detail {
template<class>
struct sfinae_true : std::true_type {};
template<class S, class T>
static auto test_lshift(int)
-> sfinae_true<decltype(std::declval<S>() << std::declval<T>())>;
template<class S, class T>
static auto test_lshift(long) -> std::false_type;
} // namespace detail
template<class T>
struct has_ostream : decltype(detail::test_lshift<std::ostream, T>(0)) {};
// using the SFINAE support stuff
template<typename T, typename std::enable_if<has_ostream<T>::value, int>::type = 0>
void PrintParams(const T& t) {
std::cout << "Type: " << typeid(t).name() << "\n"
<< " supports operator<< Value = " << t << "\n";
}
template<typename T, typename std::enable_if<!has_ostream<T>::value, int>::type = 0>
void PrintParams(const T& t) {
std::cout << "Type: " << typeid(t).name() << "\n"
<< " does NOT support operator<<\n";
}
template<typename First, typename... Rest>
void PrintParams(First first, Rest... rest) {
PrintParams(first);
PrintParams(rest...);
}
// example classes
class Foo { // will not support streaming
int x = 5;
};
class Bar { // this should support streaming
int x = 10;
friend std::ostream& operator<<(std::ostream&, const Bar&);
};
std::ostream& operator<<(std::ostream& os, const Bar& b) {
return os << b.x;
}
// testing
int main() {
int i = 2;
Foo f;
Bar b;
std::string s = "Hello world";
PrintParams(i, f, b, s);
}
Possible output:
Type: i
supports operator<< Value = 2
Type: 3Foo
does NOT support operator<<
Type: 3Bar
supports operator<< Value = 10
Type: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
supports operator<< Value = Hello world
I think std::is_class can replace your IsAUserType.
https://en.cppreference.com/w/cpp/types/is_class
Primitive data types include integer , character , void , float etc..which are defined already inside the language i.e , user can use these data types without defining them inside the language.
User defined data types are the data types which user have to define while or before using them.
I was studying about template specialization but unable to understand mixed class and int.
The following code fails to compile click to compile. Can someone suggest the right way here. I wish to specialize for int class. the second template m should be defined as 0 but how to specify that.
#include <iostream>
using namespace std;
template <class T,int m>
void fun(T a )
{
cout << "The main template fun(): " << a << " " << m << endl;
}
template<>
void fun(int a)
{
cout << "Specialized Template for int type: " << a << endl;
}
int main()
{
fun<char,10>('a');
fun<int,20>(10);
fun<float,12>(10.14);
}
The error is:
prog.cpp:11:6: error: template-id 'fun<>' for 'void fun(int)' does not match any template declaration
void fun(int a)
^
I suggest to change order of parameter to let T be deduced, then simply use overload:
template <int m, class T>
void fun(T a )
{
cout << "The main template fun(): " << a << " " << m << endl;
}
template <int m>
void fun(int a)
{
cout << "Template for int type: " << a << endl;
}
With usage:
fun<10>('a');
fun<20>(10);
fun<12, float>(10.14); // or simply fun<12>(10.14f);
I assume that what you're trying to do is to specialise the template so that any call of the form
fun<int, N>(...);
Calls the specialisation?
This would require a partial specialisation of fun() for int, but the C++ language forbids partially specialising function templates. However, we can partially specialise class templates just fine. So one approach to do what you want would be to implement your fun() function using function objects, like so:
// General case
template <typename T, int N>
struct do_fun {
void operator()(T a) {
cout << "The main template fun(): " << a << " " << N << endl;
}
};
// Specialisation for int
template <int N>
struct do_fun<int, N> {
void operator()(int a) {
cout << "Specialized Template for int type: " << a << endl;
}
};
You can then supply a wrapper function template that uses the function objects:
template <typename T, int N>
void fun(T a) {
do_fun<T, N>{}(a);
}
Coliru example
Using C++11's enable_if I want to define several specialized implementations for a function (based on the type of the parameter, say) as well as a default implementation. What is the correct way to define it?
The following example does not work as intended since the "generic" implementation is called, whatever the type T.
#include <iostream>
template<typename T, typename Enable = void>
void dummy(T t)
{
std::cout << "Generic: " << t << std::endl;
}
template<typename T, typename std::enable_if<std::is_integral<T>::value>::type>
void dummy(T t)
{
std::cout << "Integral: " << t << std::endl;
}
template<typename T, typename std::enable_if<std::is_floating_point<T>::value>::type>
void dummy(T t)
{
std::cout << "Floating point: " << t << std::endl;
}
int main() {
dummy(5); // Print "Generic: 5"
dummy(5.); // Print "Generic: 5"
}
One solution in my minimal example consists in explicitly declaring the "generic" implementation as not for integral nor floating point types, using
std::enable_if<!std::is_integral<T>::value && !std::is_floating_point<T>::value>::type
This is exactly what I want to avoid, since in my real use cases there are a lot of specialized implementations and I would like to avoid a very long (error prone!) condition for the default implementation.
You can introduce a rank to give priority to some of your overloads:
template <unsigned int N>
struct rank : rank<N - 1> { };
template <>
struct rank<0> { };
You can then define your dummy overloads like this:
template<typename T>
void dummy(T t, rank<0>)
{
std::cout << "Generic: " << t << std::endl;
}
template<typename T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
void dummy(T t, rank<1>)
{
std::cout << "Integral: " << t << std::endl;
}
template<typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
void dummy(T t, rank<1>)
{
std::cout << "Floating point: " << t << std::endl;
}
Then, you can hide the call behind a dispatch:
template <typename T>
void dispatch(T t)
{
return dummy(t, rank<1>{});
}
Usage:
int main()
{
dispatch(5); // Print "Integral: 5"
dispatch(5.); // Print "Floating point: 5"
dispatch("hi"); // Print "Generic: hi"
}
live example on wandbox
Explanation:
Using rank introduces "priority" because implicit conversions are required to convert a rank<X> to a rank<Y> when X > Y. dispatch first tries to call dummy with rank<1>, giving priority to your constrained overloads. If enable_if fails, rank<1> is implicitly converted to rank<0> and enters the "fallback" case.
Bonus: here's a C++17 implementation using if constexpr(...).
template<typename T>
void dummy(T t)
{
if constexpr(std::is_integral_v<T>)
{
std::cout << "Integral: " << t << std::endl;
}
else if constexpr(std::is_floating_point_v<T>)
{
std::cout << "Floating point: " << t << std::endl;
}
else
{
std::cout << "Generic: " << t << std::endl;
}
}
live example on wandbox
Function cannot be partially specialized. I assume what you want to do is to prefer those overloads which contains explicit condition? One way to achieve that is by using variadic arguments ellipsis in declaration of the default function as the ellipsis function have lower priority in overload resolution order:
#include <iostream>
template<typename T>
void dummy_impl(T t, ...)
{
std::cout << "Generic: " << t << std::endl;
}
template<typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
void dummy_impl(T t, int)
{
std::cout << "Integral: " << t << std::endl;
}
template<typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
void dummy_impl(T t, int)
{
std::cout << "Floating point: " << t << std::endl;
}
template <class T>
void dummy(T t) {
dummy_impl(t, int{});
}
int main() {
dummy(5);
dummy(5.);
dummy("abc");
}
Output:
Integral: 5
Floating point: 5
Generic: abc
[live demo]
Another option as #doublep mention in comment is by use of structure with implementation of your function and then partially specialize it.
I would use tag dispatching like so:
namespace Details
{
namespace SupportedTypes
{
struct Integral {};
struct FloatingPoint {};
struct Generic {};
};
template <typename T, typename = void>
struct GetSupportedType
{
typedef SupportedTypes::Generic Type;
};
template <typename T>
struct GetSupportedType< T, typename std::enable_if< std::is_integral< T >::value >::type >
{
typedef SupportedTypes::Integral Type;
};
template <typename T>
struct GetSupportedType< T, typename std::enable_if< std::is_floating_point< T >::value >::type >
{
typedef SupportedTypes::FloatingPoint Type;
};
template <typename T>
void dummy(T t, SupportedTypes::Generic)
{
std::cout << "Generic: " << t << std::endl;
}
template <typename T>
void dummy(T t, SupportedTypes::Integral)
{
std::cout << "Integral: " << t << std::endl;
}
template <typename T>
void dummy(T t, SupportedTypes::FloatingPoint)
{
std::cout << "Floating point: " << t << std::endl;
}
} // namespace Details
And then hide the boiler plate code like so:
template <typename T>
void dummy(T t)
{
typedef typename Details::GetSupportedType< T >::Type SupportedType;
Details::dummy(t, SupportedType());
}
GetSupportedType gives you one central way to guess the actual type you are going to use, that's the one you want to specialize everytime you add a new type.
Then you just invoke the right dummy overload by providing an instance of the right tag.
Finally, invoke dummy:
dummy(5); // Print "Generic: 5"
dummy(5.); // Print "Floating point: 5"
dummy("lol"); // Print "Generic: lol"
Consider the following template functions:
template <class T>
const T* DoSomething(const T& t)
{
auto& id = typeid(T);
cout << "Type is " << id.name() << ", and we have a ";
cout << "ref of one\n";
return &t;
}
template <class T>
T* DoSomething(T* t)
{
auto& id = typeid(T);
cout << "Type is " << id.name() << ", and we have a ";
cout << "pointer to one \n";
return t;
}
template <class T, template <class> class container>
T* DoSomething(const container<T>& t)
{
auto& type_id = typeid(T);
auto& container_id = typeid(container<T>);
cout << "Type is " << type_id.name() << ", and we have a ";
cout << container_id.name() << "of one\n";
return t.get();
}
template <class T, template <class,class> class container, template <class> class deleter = default_delete>
T* DoSomething(const container<T, deleter<T>>& t)
{
auto& type_id = typeid(T);
auto& container_id = typeid(container<T,deleter<T>>);
cout << "Type is " << type_id.name() << ", and we have a ";
cout << container_id.name() << "of one\n";
return t.get();
}
The goal is to be able to pass to them either a plain reference, pointer, or smart pointer, and use overloading and template specilization in order for the correct function to be called. The following driving code works as expected:
char r('r');
DoSomething(r);
DoSomething(&r);
shared_ptr<char> s(new char ('s'));
unique_ptr<char> u(new char ('u'));
DoSomething(s);
DoSomething(u);
However, consider what happens if we try this:
vector<int> v {1,2};
DoSomething(v);
Now, we we get a compile error. The version of DoSomething that the compiler decides to use is the 4th one. Inside this, we reference a function get(), which vector does not have. If the compiler were to somehow pick the 1st defintion of DoSomething, it would compile fine, and work as I intend.
So can I restrict the 3rd and 4th specializations to only be matched when the template template parameter contains a get() method? Is there a way I can get this to happen, perhaps using traits, SFINAE, or some other more advanced template technique?
The version of DoSomething that the compiler decides to use is the 4th one.
Because std::vector<T, std::allocator<T>> is an exact match for the template parameter container and std::allocator<T> is an exact match for the template parameter deleter, and const container<T, deleter<T>>& is more specialized than const T& so the 4th overload is chosen as the best match by the partial ordering rules for function templates.
So can I restrict the 3rd and 4th specializations to only be matched when the template template parameter contains a get() method?
Yes, you can tell the compiler that the function returns whatever t.get() returns:
template <class T, template <class> class container>
auto DoSomething(const container<T>& t) -> decltype(t.get())
{
auto& type_id = typeid(T);
auto& container_id = typeid(container<T>);
cout << "Type is " << type_id.name() << ", and we have a ";
cout << container_id.name() << "of one\n";
return t.get();
}
If t.get() is not a valid expression then template argument deduction fails, because the argument T cannot be substituted into the function signature successfully, and so the function will not be a viable overload, and the 1st overload will be used instead.
The OP code has a flaw when a std::unique_ptr with a custom deleter is used:
struct Deleter {
void operator()(char*) const {}
};
unique_ptr<char, Deleter> u(new char ('u'), Deleter());
DoSomething(u) // The first is applied.
Using duck typing via SFINAE is troublesome.
template <typename T, typename U>
struct X {
// Is this a get like a get of a smart pointer !?
T* get();
}
I recommend the solution of user1095108.
I'd try this:
template <typename>
struct is_smart : ::std::false_type
{
};
template <typename T>
struct is_smart<::std::shared_ptr<T> > : ::std::true_type
{
};
Use like this:
::std::cout << is_smart<container<T> >{} << ::std::endl;
But I'd rather override like this:
template <class T>
T* DoSomething(const ::std::shared_ptr<T>& t)
{
}
for every container and smart pointer type you intend to support.