问题
I have a class template defined as follow
template<typename T>
class A
{
T t_;
// void f();
};
My question is how to add the f() method only if the type T is integer without compilation error.
int main()
{
A<int> a; // OK
A<string> b; // OK
}
Example :
#include <type_traits>
#include <new>
#include <iostream>
#include <string>
template <typename T>
struct Foo
{
T t;
template <typename..., typename U = T>
std::enable_if_t<std::is_same_v<T, int>> say_hello() { std::cout << "Hello"; }
};
int main()
{
Foo<int>();
Foo<double>();
}
Error C2938 'std::enable_if_t<false,void>' : Failed to specialize alias template
Thank you.
回答1:
You can enable specific functions using type_traits
and SFINAE:
#include <iostream>
#include <string>
#include <type_traits>
template<typename T>
class A
{
public:
template<typename U = T, std::enable_if_t<std::is_integral_v<U>, int> = 0>
void f() {
std::cout << "int " << t_ << '\n';
}
private:
T t_;
};
int main() {
A<int> a;
a.f();
A<std::string> s;
// s.f(); // error: no member named 'f' in 'A<std::__cxx11::basic_string<char> >'
}
If you have many integer specific functions you can put them in a class of its own and inherit that class only if T
is integral.
#include <iostream>
#include <string>
#include <type_traits>
template<typename Atype>
class int_functions {
public:
Atype* This() { return static_cast<Atype*>(this); }
void f() {
std::cout << "int " << This()->t_ << '\n';
}
};
template<typename Atype>
class non_int_functions {
};
template<typename T>
class A : public std::conditional_t<std::is_integral_v<T>, int_functions<A<T>>,
non_int_functions<A<T>>>
{
friend std::conditional_t<std::is_integral_v<T>, int_functions<A<T>>,
non_int_functions<A<T>>>;
public:
private:
T t_;
};
回答2:
You can use partial specialization, as follows
template<typename T>
class A
{
T t_;
// void f()
};
template<>
class A<int>
{
int t_;
void f(){}
};
--Edit--
You can put your original class as a Base<T>
and the make a new class A<T>
inheriting from Base
, then partially specialized A<int>
and add your function as follows
#include<string>
template<typename T>
struct Base
{
T t_{};
};
template<typename T>
struct A:public Base<T>
{
};
template<>
struct A<int>:public Base<int>
{
void f(){
std::cout<<"in A<int>\n";
}
};
int main()
{
A<int> a; // OK
a.f();
A<std::string> b; // OK
//b.f(); //compilation error
}
来源:https://stackoverflow.com/questions/60768553/add-function-member-to-a-template-class-conditionally