Consider the following code:
template <typename T>
struct S
{
template <typename = void>
static constexpr bool B = true;
template <std::enable_if_t<S<T>::template B<>, int> = 0>
void f();
};
template <typename T>
template <std::enable_if_t<S<T>::template B<>, int>>
void S<T>::f() {}
gcc accepts this, but clang rejects it with:
error: out-of-line definition of 'f' does not match any declaration in 'S<T>'
This has been asked about before, but there is no answer there.
On the other hand, if B
is not a template, and I write this code:
template <typename T>
struct S
{
static constexpr bool B = true;
template <std::enable_if_t<S<T>::B, int> = 0>
void f();
};
template <typename T>
template <std::enable_if_t<S<T>::B, int>>
void S<T>::f() {}
clang accepts this, but gcc rejects the code with:
error: no declaration matches 'void S<T>::f()'
So are either of these snippets valid?
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
Which of the following is true about templates. 1) Template is a feature of C++ that allows us to write one code for different data types. 2) We can write one function that can be used for all data types including user defined types. Like sort(), max(), min(), ..etc.
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.
A template is a predesigned document you can use to create documents quickly without having to think about formatting. With a template, many of the larger document design decisions such as margin size, font style and size, and spacing are predetermined.
During the definition of S<X>
it is an incomplete type. And the class member access operator requires a complete type.
But you could solve the situation with the following code:
#include <type_traits>
template <typename T>
struct S {
template <typename = void>
static constexpr bool B = true;
template <
typename TX = T,
std::enable_if_t<S<TX>::template B<>, int> = 0>
void f();
};
template <typename T>
template <typename TX, std::enable_if_t<S<TX>::template B<>, int>>
void S<T>::f() {}
//-----------
template <typename T>
struct S2 {
static constexpr bool B = true;
template <
typename TX = T,
std::enable_if_t<S2<TX>::B, int> = 0>
void f();
};
template <typename T>
template <typename TX, std::enable_if_t<S2<TX>::B, int>>
void S2<T>::f() {}
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