I have followed this post: Class template SFINAE to instantiate the template class conditionally.
That works perfectly for the classes which have only one template parameters, as shown in the link above.
However, I have two (template)arguments, and I would like to do certain SFINE check. Following is a minimal example of my code.
#include <type_traits>
#include <string>
template<class T, class U, class R> using arithmetic_types = std::enable_if_t<
std::is_arithmetic_v<T> &&
std::is_arithmetic_v<U>,
R
>;
template<class T, class U, class Enable = void> class MyClass;
template<class T, class U, arithmetic_types<T, U, void>>
class MyClass {
public:
MyClass() = default;
};
int main()
{
MyClass<int, int> o; // should work
MyClass<int, double> o1; // should work
MyClass<int, std::string> o2; // should be a complier error
return 0;
}
Above gave me the error message: https://godbolt.org/z/BEWJMp
error C3855: 'MyClass': template parameter 'Enable' is incompatible with the declaration
error C2079: 'o' uses undefined class 'MyClass'
error C2079: 'o1' uses undefined class 'MyClass'
error C2079: 'o2' uses undefined class 'MyClass'
Unfortunately, I could not understand the error message(error C3855:
).
Why I can't do the same principle shown in the above link to more template parameters?
And what is the best solution for this?
To instantiate a template class explicitly, follow the template keyword by a declaration (not definition) for the class, with the class identifier followed by the template arguments. template class Array<char>; template class String<19>; When you explicitly instantiate a class, all of its members are also instantiated.
Inheriting from a template class It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
A template can take a parameter that is itself the name of a template. These parameters have the pleasingly repetitious name of template template parameters. template <typename T, template <typename> class Cont> class Stack; This new template parameter list for Stack looks unnerving, but it's not as bad as it appears.
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
The problem is in the template specialization of MyClass. The specialization should be parameterized only on the two classes T
and U
, the test should be put in the declaration, as in the example below.
#include <string>
#include <type_traits>
template <class T, class U, class R>
using arithmetic_types = std::enable_if_t<
std::is_arithmetic_v<T> && std::is_arithmetic_v<U>, R>;
template <class T, class U, class Enable = void>
class MyClass;
template <class T, class U> //<- Remove the test from here
class MyClass<T, U, arithmetic_types<T, U, void>> //<- Put the test here.
{
public:
MyClass() = default;
};
int main()
{
MyClass<int, int> o; // should work
MyClass<int, double> o1; // should work
MyClass<int, std::string> o2; // should be a complier error
return 0;
}
Demo: https://godbolt.org/z/xTnwo9
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With