3
template <typename X, typename Y> class A {
    // Use Y::Q, a useful property, not used for specialization.
};
enum Property {P1,P2};
template <Property P> class B {};
class C {};

有没有办法定义这样的部分专业化,AA<C, B<P1> >将是A正常的模板,但A<C, B<P2> >会是专业化吗?

针对 Marcelo 进行编辑:更具体地说,不应仅使用 B 选择专业化,还应选择具有特定属性的任何类型,例如它是第一个参数为 P2 的模板。

目标是为Y提供一个漂亮的界面A,允许编写类似A<C, Y<P2,Q> >.


用模板模板参数替换Y模板参数会很好,但是有没有办法在此基础上对其进行部分专门化P

目的是编写如下内容:

template <typename X, template <Property P> typename Y> class A {};
template <typename X> class A<X,template<> Y<P2> > {}; // <-- not valid

编辑以回应 In silico:我说制作模板模板参数会很好Y,但实际上这违背了我想要做的目的,即用于Y将逻辑链接的属性组合在一起,但仍然A基于一个那些子属性。


有没有办法通过将特征添加到专业化template <> class B<P2>然后在中使用 SFINAE A?目的是编写如下内容:

template <> class B<P2> {
    typedef int IAmP2;
};

// The following is not valid because it's a simple redefinition.
template <typename X, typename Y> class A {
    // Substitution using this template would fail for Y<P1>, and only the 
    // general template would be left for selection.
    typename Y::IAmP2 skipIfNotP2;
};
4

4 回答 4

4

我不明白你的意思。模板模板参数似乎是解决方案,尽管您以某种方式说它们不起作用。为什么不这样做?

template <typename X, typename Y> 
class A {
};

template <typename X, template<typename> class Y, typename P> 
class A< X, Y<P> > {
  /* property is P */
};

对于您的 SFINAE 问题,是的,这也是可能的

template <typename X, typename Y, typename Sfinae = void> 
class A {
};

template <typename X, typename Y> 
class A< X, Y, typename Y::IAmP2 > {
  /* Y is the class having a property */
};

class Sample {
  typedef void IAmP2;
};

我仍然不确定你的意思。

于 2010-05-29T12:00:17.110 回答
0

如果没有模板模板参数(我不知道在这种情况下使用),它应该相当简单:

template <> class A<C, B<P2> > { ... };

太简单了,其实。我一定错过了什么,但我看不到什么。

于 2010-05-29T06:49:50.337 回答
0

这是你想要的吗?(使用 Visual Studio 2005 测试)

enum Property { P1, P2 }; 

template <Property P> class B {}; 
class C {};

// Other similar types, for the purpose of testing
template <Property P> class AnotherB {};
class AnotherC {};

// Primary template
template <typename X, template<Property P> class Y, Property P> class A
{
public:
    A() { ::printf("Primary template\n"); }
};

// Partial specialization for P2
template <typename X, template<Property P> class Y> class A<X, Y, P2>
{
public:
    A() { ::printf("Partially specialized template\n"); }
};

int main()
{
    // Trying out some combinations
    A<C, B, P1> q;               // prints "Primary template"
    A<C, B, P2> w;               // prints "Partially specialized template"
    A<AnotherC, B, P1> e;        // prints "Primary template"
    A<AnotherC, B, P2> r;        // prints "Partially specialized template"
    A<C, AnotherB, P1> t;        // prints "Primary template"
    A<C, AnotherB, P2> y;        // prints "Partially specialized template"
    A<AnotherC, AnotherB, P1> u; // prints "Primary template"
    A<AnotherC, AnotherB, P2> i; // prints "Partially specialized template"
}

您尝试部分特化会导致编译器错误,因为您只能将 模板传递给模板模板参数。您不能传入template <> class B<P2>模板模板参数,因为它是完整类型,而不是模板。

对于main()函数中的前两行代码,C是一个完整的类型,我们传递给A类型参数XB是我们传递给A模板参数的模板Y,并且该模板必须接受 aProperty作为唯一的模板参数。我们将一个Property值(P1P2)分别传递给A非类型参数P。当我们传入P2模板的最后一个参数时A,编译器将看到特化并使用它——否则,编译器将使用主模板A。接下来的 6 行遵循类似的模式。

于 2010-05-29T07:01:17.923 回答
0

我将提供另一个答案来回应您对Matrix示例的评论。

对于您的Matrix示例,您可以这样做:

enum MatrixOrder { ColumnMajor, RowMajor };

template<MatrixOrder Order> class Dense {};
template<MatrixOrder Order> class Sparse {};

template<typename T, template<MatrixOrder> class Storage, MatrixOrder Order>
class Matrix
{
public:
    Matrix() { ::printf("Primary\n"); }
};

template<typename T, MatrixOrder Order>
class Matrix<T, Dense, Order>
{
public:
    Matrix() { ::printf("Specialized\n"); }
};

int main()
{
    // Trying out some combinations...
    Matrix<double, Dense, ColumnMajor> a;  // Prints "Specialized"
    Matrix<double, Dense, RowMajor> b;     // Prints "Specialized"
    Matrix<double, Sparse, ColumnMajor> c; // Prints "Primary"
    Matrix<double, Sparse, RowMajor> d;    // Prints "Primary"
    Matrix<float, Dense, ColumnMajor> e;   // Prints "Specialized"
    Matrix<float, Dense, RowMajor> f;      // Prints "Specialized"
    Matrix<float, Sparse, ColumnMajor> g;  // Prints "Primary"
    Matrix<float, Sparse, RowMajor> h;     // Prints "Primary"
    return 0;
};

它与我上一个答案的模式相似。现在,所有采用的存储方案Dense都将专门化。希望这会有所帮助,至少有一点帮助。:-)

于 2010-05-29T08:03:44.900 回答