This question already has answers here:
std:: add_pointer, what the try_add_pointer for in the possible implementation?
(2 answers)
Closed 2 years ago.
I've been hacking around the standard library lately, since I need to implement a subset of it (mostly template stuff) for a system which doesn't have an stdlib implementation.
I came across this "possible implementation", in cppreference:
namespace detail {
template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
template <class T>
auto try_add_pointer(int) -> type_identity<typename std::remove_reference<T>::type*>;
template <class T>
auto try_add_pointer(...) -> type_identity<T>;
} // namespace detail
template <class T>
struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
and I've been wondering why do you need SFINAE here. Isn't this:
template< class T >
struct add_pointer {
typedef typename std::remove_reference<T>::type* type;
};
enough? which instantiation takes the second case of try_add_pointer? I tried to think about it but couldn't think about any such case.
I'm not sure if this is the only bad case, but your implementation fails for so-called "abominable function types":
add_pointer<void() const>::type // hard error instead of void() const
Related
Imagine I have a concept that checks for some trait of a member type, e.g. its integralness. In anticipation of what is to come, let me define it in two ways:
namespace decayedAtConcept {
template <typename T>
concept hasIntegralMemberType = std::integral<typename std::decay_t<T>::MemberType>;
}
namespace notDecayedAtConcept {
template <typename T>
concept hasIntegralMemberType = std::integral<typename T::MemberType>;
}
With the following definitions
struct HasIntegralMemberType {using MemberType = int;};
struct HasNonintegralMemberType {using MemberType = double;};
struct DoesNotHaveMemberType {};
and the following function declarations
void usesIntegralMemberType1 (decayedAtConcept::hasIntegralMemberType auto&&);
void usesIntegralMemberType2 (notDecayedAtConcept::hasIntegralMemberType auto&&);
template <typename T> requires notDecayedAtConcept::hasIntegralMemberType<std::decay_t<T>>
void usesIntegralMemberType3 (T&&);
in effect, a client can try to use this library in the following way:
void client () {
HasIntegralMemberType h;
usesIntegralMemberType1(HasIntegralMemberType{});
usesIntegralMemberType1(h); // OK
//usesIntegralMemberType1(HasNonintegralMemberType{}); //note: constraints not satisfied
//usesIntegralMemberType1(DoesNotHaveMemberType{}); //note: constraints not satisfied
usesIntegralMemberType2(HasIntegralMemberType{});
//usesIntegralMemberType2(h); //error: ‘HasIntegralMemberType&’ is not a class, struct, or union type
usesIntegralMemberType3(HasIntegralMemberType{});
usesIntegralMemberType3(h); // OK again
}
The notes just demonstrate that the concept works as expected in usesIntegralMemberType1. My question is related to the error caused by the naive usage of the notDecayedAtConcept in usesIntegralMemberType2.
Apparently, the notDecayedAtConcept version of the concept is less convenient to use because any time it is used with a universal reference, it needs to be decayed in a requires clause as in usesIntegralMemberType3. We even lose the syntactic sugar we had in defining the constrained template parameter in usesIntegralMemberType1.
And now the question: are there already some guidelines which of the two strategies to use in such a situation? Or, is there any other, more transparent/convenient solution?
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 2 years ago.
I know people have asked similar questions in this area, but I can not seem to find a solution to my exact problem. I have a LinkedList and LinkedListIterator class structured as so.
template <typename T>
class LinkedList
{
public:
template <typename NodeType>
class LinkedListIterator
{
public:
const LinkedListIterator<NodeType>& operator++();
}
};
I am trying to implement the operator++() function in a separate file and my attempt is as follows.
template <typename T>
template <typename NodeType>
const typename LinkedList<T>::LinkedListIterator<NodeType>&
LinkedList<T>::LinkedListIterator<NodeType>::operator++()
{
// Implementation here
}
Now when I try to use this class, my compiler throws an error saying non-template ‘LinkedListIterator’ used as template. Now I know I have to use typename in the definition of this function since I have dependent scopes occurring. But I can not seem to be able to fix this. I do not understand how this is seen as non-template.
Add template keyword before LinkedListIterator so compiler knows it is a template and not e.g. a field
template <typename T>
template <typename NodeType>
const typename LinkedList<T>::template LinkedListIterator<NodeType>&
LinkedList<T>::LinkedListIterator<NodeType>::operator++()
{
// Implementation here
}
This question already has answers here:
Is it possible to define an alias for a template-template parameter?
(2 answers)
Closed 3 years ago.
I have the following piece of code which does not compile -> http://ideone.com/bL9DF1.
The problem is that I want to get the template template parameter out of a type. What I have is using S = A<int, std::vector> and I want to get back that I used std::vector in making S and to use it somewhere else.
#include <iostream>
#include <vector>
template <typename T, template<class...> class Container>
struct A
{
using Ttype = T;
using ContainerType = Container;
Container<T> s;
};
int main()
{
using S = A<int, std::vector>;
S::ContainerType<double> y;
y.push_back(2);
return 0;
}
I don't know if there is even a way of doing what I want. Without the template parameters added std::vector is not a type.
You could declare ContainerType as an alias template, since Container is a template itself.
template<typename... X>
using ContainerType = Container<X...>;
LIVE
This question already has answers here:
Checking for existence of an (overloaded) member function
(3 answers)
Closed 5 years ago.
Consider the following, I want to check if the types I pass off to some other function sf has a member function T::mf that is required by sf, I know the return type and the name but there can by any number of overloads.
After some tinkering (well it is fun..) and googling , I can get something like the code below to work, the problem is that I don't know how to express that print can have a variable number of arguments.
#include <type_traits>
#include <utility>
template <typename T,typename = void>
struct has_write : std::false_type {};
template <typename T>
struct has_write<T, decltype(std::declval<T>().write())> : std::true_type {};
template <typename T, typename R = void , typename ...Args>
struct has_print : std::false_type {};
// cant deduce, specialization never used
template <typename T, typename ...Args>
struct has_print<T, decltype(std::declval<T>().print(std::declval<Args>()...))> : std::true_type {};
struct Foo {
void write();
};
struct Bar {
int print(int, float, int);
};
int main(){
static_assert(has_write<Foo>::value, "Does not have write..");
static_assert(has_print<Bar>::value, "Does not have print..");
return 0;
}
The above compiles with g++ but the second assert fails, clang is a bit more helpful and tells me that the specializations for has_print will never be used because it cannot deduce all the types.
Since you will be calling your overload from within sf function, you should check for availability of the particular overload using the types sf function would call it with.
General checking for availability of any overload within a class would always be an XY problem by definition, because availability of any overload is never important. You need to know you can call a name with given set of arguments. Consider this: asking for availability of any overload of a given name is conceptually the same as asking if particular class has any method at all. And obviously you would not be interested in it?
This question already has answers here:
C++ template constructor
(10 answers)
Closed 7 years ago.
I have recently adopted the pattern of Almost Always Auto in C++14, but have come across a case that I can't figure out how to write using the auto syntax: templated constructors.
Say I have the class:
class my_type{
public:
template<typename T>
my_type(){/* ... */}
};
I tried:
auto var = my_type<float>{};
Which, of course, doesn't work because that presumes my_type is a template and not its constructor.
then how could I use auto syntax to initialize this variable?
Although it isn't really about auto, there is a way to select templated ctors if you want to - you need to cheat, and give them an argument.
struct A {
private:
template <typename T> struct TypeWrapper {};
template <typename T> explicit A(TypeWrapper<T>) {}
public:
template <typename T>
static A make_A() {
return A(TypeWrapper<T>{});
}
};
int main() {
auto i = A::make_A<int>();
auto d = A::make_A<double>();
auto r = A::make_A<A>();
// etc. etc.
}