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.
Related
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?
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.
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
This question already has answers here:
Templated check for the existence of a class member function?
(33 answers)
SFINAE To detect non-member function existence
(1 answer)
Closed 6 years ago.
I have defined many objects, and for some of them, i defined a function :
template <typename Ratio>
auto print(const T &t, bool a= true, bool b= true)
{
std::stringstream ss;
// ... do stuff ...
return ss.str();
}
where T is the type of one of the objects for which print is defined. Ratio is used inside the function.
My question is :
Is there a way for a type T to find if this function exists ?
For others uses, i already used templates and SFINAE to detect if a class member method exists. But for my problem here, i can't find the solution ... Anyone ?
Thanks,
Ben
PS : Example of SFINAE use in my code, where i needed to detect if a class member method exists .
static T none() { ... }
/**
* SFINAE for checking id none method exists
*/
template <class T>
static auto hasNoneMethod(int)
-> std::integral_constant<bool, std::is_same<T, decltype(T::none())>::value>;
template <class>
static auto hasNoneMethod(...) -> std::false_type;
/**
* Type-Function
*/
template <typename T>
struct HasNoneMethod: decltype(detail::hasNoneMethod<T>(0)) {
};
You may use something like this:
template <class T>
static auto hasPrintMethod(int)
->std::integral_constant<bool, std::is_class<decltype(print(T()))>::value>;
template <class>
static auto hasPrintMethod(...)->std::false_type;
template <typename T>
struct HasPrintMethod : decltype(hasPrintMethod<T>(0)) {
};
Here the decltype(print(T())) is std::string for classes for which your non-member function is defined, and an erroneous type for other classes. So, according to SFINAE concept, HasPrintMethod<A>::value is equal to true for class A with print function defined and is equal to false otherwise.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to write a C++ template to check for a function's existence?
I am trying to write a C++ class template. What I want is when this class template is used with user defined classes, I want to force those user defined classes to implemented certain methods say e.g., to_data and from_data. I do not want those for basic C++ primitive datatypes. How do I do this? For example, std::vector give compilation error if the copy constructor of the class is not available.
You can make the methods that must be implemented by user pure virtual functions. If you don't want those for basic C++ primitive datatypes, you can specialize your template for these situations and provide default implementations for these cases.
Simply use the methods in your class template:
template <typename T>
struct Serializer
{
void serialize(T const & t) const { write(t.to_data()); }
void deserialize(T & t) const { t.from_data(read()); }
};
If the types you instantiate the template with have the appropriate member functions, everything will be fine. If they don't, the compiler will trigger an error:
struct Foo
{
int val;
int to_data() const { return val; }
void from_data(int i) { val = i; }
};
struct Bar {};
Serializer<Foo> sf;
sf.serialize(); // OK
Serializer<Bar> sb;
sb.serialize(); // compiler error: Bar has no member function named "to_data"
Note that the compiler error is only triggered when we try to use some functions of the class template. This is because member functions of class templates are only instantiated (compiled, if you will) when you use them. So it is perfectly fine to instantiate Serializer with Bar as long as you don't use the serialize and deserialize member function.
Regarding the second issue, namely how to provide a different behavior for primitive types, you have several solutions. The first one is to specialize your class template for the types you want to handle differently. For instance, the following code specializes Serializer so that it handles int differently:
template <>
struct Serializer<int>
{
void serialize(int i) const { write(i); }
void deserialize(int & i) const { i = read();
};
However, this implies writing a specialization for each particular type, even if some of them are in fact handled in the same way.
A less cumbersome solution would be to use type traits and std::enable_if to select the correct implementation depending on some characteristics of the arguments types (in this case, whether they are primitive or not):
#include <type_traits>
template <typename T, typename Enable = void>
struct Serializer
{
// same as before
};
// Partial specialization for fundamental types
template <typename T>
struct Serializer<T, typename
std::enable_if<std::is_fundamental<T>::value>::type>
{
void serialize(T t) const { write(t); }
void deserialize(T & t) const { t = read(); }
};
Serializer<Foo> sf; // first implementation
Serializer<int> si; // second (specialized) implementation