我有一个特质课,我需要多次专攻(和部分特化)。
部分专业化重叠:
template< typename T > struct C { };
template< typename T1, typename T2 > struct TRAIT { };
template< typename T > struct TRAIT< T, T > { };
template< typename T1, typename T2 > struct TRAIT< C<T1>, C<T2> > { };
int main( ) {
// ERROR! could be both TRAIT<T,T> [with T = C<int>]
// and TRAIT<T1,T2> [with T1 = T2 = int]
TRAIT< C<int>, C<int> > foo;
return 0;
};
我应该如何使用正常的代码获得相同的结果?
我对enable_if
和is_same
发疯了,我甚至不确定它是否正确......
答案 0 :(得分:6)
如果您无法避免重叠专业化,那么您最好的选择就是澄清所有重叠。您需要为
编写另一个专门化template< typename T> struct TRAIT< C<T>, C<T> > { };
...但是,正如其他人在评论中所说的那样,最好尽量避免重叠。正如其他人所说,问题可能不是重叠的专业化,可能这不是解决问题的最佳方法。
答案 1 :(得分:1)
诀窍是创建一个帮助器类型,告诉你某些东西是否是C<Foo>
:
template <typename T> struct C {};
template <typename T> struct is_C {
static bool const value = false;
};
template <typename T> struct is_C<C<T>> {
static bool const value = true;
};
您使用enable_if
走在正确的轨道上,但is_same
似乎是一个死胡同:
#include <type_traits>
template <typename T1, typename T2, typename Enabled = void> struct Trait {
static char const test = 'D'; // default
};
template <typename T> struct Trait<
T,
T,
typename std::enable_if<!is_C<T>::value >::type
> {
static char const test = 'N'; // non-C
};
template <typename T1, typename T2> struct Trait<
T1,
T2,
typename std::enable_if< is_C<T1>::value && is_C<T2>::value >::type
> {
static char const test = 'C'; // some C
};
您现在可以轻松测试:
#include <iostream>
int main() {
Trait< C<int>, C<float> > foo1a;
Trait< C<int>, C<int> > foo1b;
Trait< int, int > foo2;
Trait< int, float > foo3;
std::cout << "Trait<C<int>,C<float>> : " << foo1a.test << std::endl; // prints 'C'
std::cout << "Trait<C<int>,C<int>> : " << foo1b.test << std::endl; // prints 'C'
std::cout << "Trait<int,int> : " << foo2.test << std::endl; // prints 'N'
std::cout << "Trait<int,float> : " << foo3.test << std::endl; // prints 'D'
return 0;
}
如果您希望专业化仅使用其中一个参数C
或您喜欢的任何参数,则可以轻松更改。
答案 2 :(得分:0)
尝试:
template< typename T > struct C { };
template< typename T1, typename T2 = T1> struct TRAIT { };
// ^^^^^^^^^
// Default Type is T1
int main( )
{
TRAIT<C<int> > foo1;
TRAIT<C<int>, C<int> > foo2;
foo1 = foo2;
return 0;
};