模糊的部分模板专业化

时间:2010-12-06 21:20:44

标签: c++ templates specialization ambiguity

我有一个特质课,我需要多次专攻(和部分特化)。

部分专业化重叠:

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_ifis_same发疯了,我甚至不确定它是否正确......

3 个答案:

答案 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;
};