Template member switch using enable_if and is_default_constructible [duplicate] - c++

This question already has answers here:
Member function template selection and SFINAE
(1 answer)
SFINAE not working to conditionally compile member function template
(1 answer)
Approaches to function SFINAE in C++
(2 answers)
Closed 2 years ago.
I want to switch between to members of a templatized class based on the fact the type of the template is default constructible or not.
I think I'm not far from the solution after a lot of reading and tries around std::enable_if and std::is_default_constructible, but I'm still stuck at compile-time, here's a minimized exemple :
template<typename DataType>
class MyClass{
public:
template < typename = typename std::enable_if_t<std::is_default_constructible_v<DataType>>>
inline void createNew(unsigned int index) {
new (&this->buffer[index]) DataType(); // "placement new"
}
template < typename = typename std::enable_if_t<!std::is_default_constructible_v<DataType>>>
inline void createNew(unsigned int index) {
throw BaseException("No default constructor");
}
};
This last try results on "member function already defined or declared". I think I miss something, but I don't understand why both functions are selected for compilation even if they have the exact opposite template condition.

Related

C++ different template specialisation for constuctor with vectors of unknown type [duplicate]

This question already has answers here:
Partial template specialization for constructor
(1 answer)
how to specialize a template constructor
(1 answer)
Closed 8 months ago.
I'm trying to make a constructor in a templated class act differently if its template parameter is a vector, but am getting an error on the second definition saying "template argument list must match the parameter list". This is what my code looks like:
template<typename T>
class Test
{
Test();
};
template<typename T>
Test<T>::Test() { /* non-vector stuff */ };
template<typename T>
Test<std::vector<T>>::Test() { /* vector stuff */ };
Does anyone know how to do this?

Multiple std::hash specialisation [duplicate]

This question already has answers here:
Specializing `std::hash` for classes meeting condition
(3 answers)
Closed 1 year ago.
I have a class
class Base {
...
virtual size_t GetHash() = 0;
...
};
and a number of classes, inherited from Base, that override GetHash().
I want to use these classes as a key in unordered_map or unordered_set. Currently I achieve it by using
struct HashKey
{
template <typename T>
size_t operator()(const T & obj) const
{
return obj.GetHash();
}
};
as a Hash class in unordered_map template (like unordered_map<MyDerived, int, Hashkey>).
According to this question, I can explicitly specialize std::hash<T> for my own class and totally works fine, but I'm interested if there any way to specialize it for multiple classes?
I'm using C++17
Yes. Make it work for all T where T has a base class of Base.
Without requires, this is done using SFINAE and enable_if.

Concept for member function taking a template parameter in C++20 [duplicate]

This question already has answers here:
How can unspecified types be used in C++20 'requires' expressions?
(2 answers)
How to type-erase a C++ concept
(2 answers)
Closed 1 year ago.
I would like to have a concept for the
struct creatorclass {
template<typename T>
int fct(T val)
{
return 42;
}
};
What I would like is a concept that checks for the existence of a function fct without specifying the template parameter. That is want to have
template<typename U>
concept CREATOR=requires(U val) {
val.fct;
};
I think that this is not possible since a concept needs to be evaluated and so compiled. This cannot be done without knowing the class T. Am I correct?
Note: Specifying a concept for a type that has a member function template using Concepts Lite also says this is not possible but this is for concept-lite six years ago before the C++20 standard.
As far as I am aware, it is not possible to test for a template member function without evaluating any of the template parameters.
That said, if you have an idea of what the classification of inputs are allowed to be -- such as if a function can only be evaluated with integral-values or something like this -- then you can test it with an explicit instantiation which may be 'good enough' for whatever your purposes are:
template<typename U>
concept CREATOR=requires(U val) {
// Checks that 'val' has a 'fct' function template that works with integers
val.template fct<int>(5);
};
Live Example
In most cases, however, its generally more useful for a concept to be defined around the complete atomic definition required to fulfill its contract -- at which point its generally better to punt this evaluation off to a template argument as well:
template <typename T, typename U>
concept fnc_evaluatable = requires(T val, U in) {
val.template fct<U>(in);
};
And then use this in greater compositions.
At this point, the state of fnc being a template also becomes less important than the state of it having a member function call fct that is callable by a U -- and can likely be simplified to just:
template <typename T, typename U>
concept fnc_evaluatable = requires(T val, U in) {
val.fct(in);
};

Partial Template Specialization doesnt work [duplicate]

This question already has answers here:
C++ function template partial specialization?
(7 answers)
Why function template cannot be partially specialized?
(4 answers)
Closed 2 years ago.
I am very new to modern C++ and am trying to do something as described below, which throws error on partial template specialization but works completely fine on complete specialization.
What am I doing here?
Language version: C++14
Compiler: GreenHills (GHS)
Doesnt work
template<bool isPrefix>
struct my_struct;
template<>
struct my_struct<true> // specializes true
{
... some data members...
char prefix_data[10]
}
template<>
struct my_struct<false> // specializes false
{
... only other data members...
// no prefix data member variable
}
template<bool isEnabled, class T>
void prefixData(const T& data)
{
// performing some operation on T
data.prefix_data[0] = 0x01;
}
// DOES NOT WORK, THROWS COMPILATION ERROR
template<class T>
void prefixData<false, T>(const T& data)
{
// no logic required here
}
However, if I specify complete specialization for the function it works.
This Works
template<>
void prefixData<false, my_struct<false>>(const T& data)
{
}
P.S: I want to avoid run-time polymorphism (abstract class + inheritance) since the code will run on embedded platform with limited resources
I want to avoid explicit specialization of each cases. I have explained here with just isPrefix in my_struct. My actual code contains more template variables.

How to use SFINAE with nullary member function? [duplicate]

This question already has answers here:
Selecting a member function using different enable_if conditions
(6 answers)
Closed 6 years ago.
I have a class template Bird with a Boolean template parameter can_fly. Depending on that value, I want to enable a member function with the signature void fly();.
This is my code:
#include <type_traits>
template<bool can_fly>
class Bird {
public:
template<typename void_t = typename std::enable_if<can_fly>::type>
void_t fly() { /* ... */ }
};
int main() {
Bird<true> flyingBird;
flyingBird.fly();
Bird<false> flightlessBird;
return 0;
}
This code compiles fine in Visual Studio 2015, but GCC complains that there is "no type named 'type' in 'struct std::enable_if'" in the third line of main.
I thought the fact that there is no ::type in the false case was the entire point of SFINAE. Can somebody explain to me what I did wrong and what the correct approach is?
As mentioned in this answer:
enable_if works because the substitution of a template argument resulted in an error, and so that substitution is dropped from the overload resolution set and only other viable overloads are considered by the compiler.
In your case there is no substitution because can_fly is known at the moment of instantiation. You can create a dummy default bool template parameter to make SFINAE work properly:
template<bool can_fly>
class Bird {
public:
template<bool X = can_fly, typename = typename std::enable_if<X>::type>
void fly() { /* ... */ }
};
wandbox example