提问人:TreeTownGreen 提问时间:9/20/2023 更新时间:9/20/2023 访问量:80
按类型特征划分的 C++ 模板方法专业化
C++ template method specialization by type traits
问:
我正在使用 C++ 11,创建一个类模板。我希望根据模板参数的类型特征(即浮点数/整数、有符号/无符号等)优化某些方法。我知道这可以通过对每个特定特征组合的模板专业化来实现,但这太笨拙了。
取而代之的是,我使用虚拟结构包装器的部分模板专用化来工作(因为据我所知,部分专用化仅适用于结构/类)。
这里的工作示例:
#include<type_traits>
#include<iostream>
template<typename T>
struct A
{
A( T _x ) : x(_x) {}
template<typename U, bool foobar = std::is_signed<T>::value>
struct temp{};
template<typename U>
struct temp<U,true>
{
static constexpr U diff( A const &left, A const &right ) noexcept
{
std::cout << "Signed" << std::endl;
T d = left.x - right.x;
return d * d;
}
};
template<typename U>
struct temp<U,false>
{
static constexpr U diff( A const &left, A const &right ) noexcept
{
std::cout << "Unsigned" << std::endl;
T d = left.x < right.x ? right.x - left.x : left.x - right.x;
return d * d;
}
};
protected:
T x;
};
int main( int argc, char** argv )
{
// Unsigned
A<unsigned int> u1( 10 );
A<unsigned int> u2( 15 );
// Method call
std::cout << A<unsigned int>::temp<unsigned long>::diff( u1, u2 ) << std::endl;
// Signed
A<float> f1( -1.23f );
A<float> f2( 12.3f );
// Method call
std::cout << A<float>::temp<double>::diff( f1, f2 ) << std::endl;
}
从模板用户的角度来看,取消引用虚拟结构很麻烦,所以如果可能的话,我特别想改进它。
我对C++的了解远非百科全书,所以我想知道是否有更好的解决方案。最好是C++ 11兼容,但我也很想听听现代C++的替代品。
显然我已经用谷歌搜索过这个,但需要我所有的搜索技能才能使上述内容正常工作。
提前致谢。
答:
1赞
NathanOliver
9/20/2023
#1
你把它弄得太复杂了。您可以向类添加模板重载,并将这些重载限制为特定条件。为此,您将使用
template<typename T>
struct A
{
A( T _x ) : x(_x) {}
template<typename U, bool foobar = std::is_signed<T>::value>
struct temp{};
// only enabled if U or by default T is signed
template<typename U = T, typename std::enable_if<std::is_signed<U>::value, bool>::type = true>
static constexpr U diff( A const &left, A const &right ) noexcept
{
std::cout << "Signed" << std::endl;
T d = left.x - right.x;
return d * d;
}
// only enabled if U or by default T is unsigned
template<typename U = T, typename std::enable_if<!std::is_signed<U>::value, bool>::type = true>
static constexpr U diff( A const &left, A const &right ) noexcept
{
std::cout << "Unsigned" << std::endl;
T d = left.x < right.x ? right.x - left.x : left.x - right.x;
return d * d;
}
protected:
T x;
};
然后你的司机变成
int main()
{
// Unsigned
A<unsigned int> u1( 10 );
A<unsigned int> u2( 15 );
// Method call
std::cout << A<unsigned int>::diff( u1, u2 ) << std::endl;
// Signed
A<float> f1( -1.23f );
A<float> f2( 12.3f );
// Method call
std::cout << A<float>::diff( f1, f2 ) << std::endl;
}
如此实时示例所示
评论
0赞
TreeTownGreen
9/20/2023
感谢您如此及时和有用的回复。工作是一种享受。我喜欢 U != T 的语法很直观,例如 A<float>::d iff<double>( f1, f2 )。再次感谢!
评论