部分模板特化:匹配特化模板参数的属性

发布于 2024-09-03 02:17:46 字数 1509 浏览 1 评论 0 原文

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 {};

有没有办法定义 A 的部分特化,使得 A > 将是 A 的普通模板,但 A > 会是专业化吗?

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

目标是使用 YA 呈现一个漂亮的界面,允许编写类似 A 的内容。 >


用模板模板参数替换 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


有没有一种方法可以将特征添加到专门化模板<>中?类 B 然后在 A 中使用 SFINAE?目的是写一些类似的东西:

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;
};
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 {};

Is there any way to define a partial specialization of A such that A<C, B<P1> > would be A's normal template, but A<C, B<P2> > would be the specialization?

Edit in response to Marcelo: More specifically, the specialization should be chosen not just with B, but with any type that exhibits a certain property, for example that it's a template whose first argument is P2.

The goal is to use Y to present a nice interface for A, allowing to write something like A<C, Y<P2,Q> >.


Replacing the Y template parameter by a template template parameter would be nice, but is there a way to partially specialize it based on P then?

The intention would be to write something like:

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

Edit in response to In silico: I said it would be nice to make Y a template template parameter, but actually that defeats the purpose of what I wanted to do, which is to use Y to group logically linked properties together, but still specialize A based on one of those sub-properties.


Is there a way by adding traits to a specialization template <> class B<P2> and then using SFINAE in A? The intention would be to write something like:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沉溺在你眼里的海 2024-09-10 02:17:46

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

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

但我仍然不确定您的意思。

I've no idea what you mean. Template template parameters seem the solution, although you somehow say they won't work. Why not do this?

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

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

For your SFINAE question, yes that is possible too

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

Still i'm not sure what you mean at all.

老子叫无熙 2024-09-10 02:17:46

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

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

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

Without template template parameters (which I wouldn't know to use in this context), it should be fairly simple:

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

Too simple, in fact. I must be missing something, but I can't see what.

烟燃烟灭 2024-09-10 02:17:46

这是你想要的吗? (使用 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"
}

您尝试部分专业化会导致编译器错误,因为您只能通过
templates 到模板模板参数。您无法传入 template <> class B 作为模板模板参数,因为它是完整类型,而不是模板。

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

Is this what you want? (Tested with 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"
}

Your attempt at partial specialization causes compiler errors because you can pass only
templates to template template parameters. You can't pass in template <> class B<P2> for a template template parameter because it's a complete type, not a template.

For the first two lines of code in the main() function, C is a complete type we're passing in to A's type parameter X. B is the template we're passing in to A's template parameter Y, and that template has to accept a Property as the only template parameter. We pass in a Property value (either P1 or P2) to A's nontype parameter P separately. When we pass in P2 for the last argument of the template A, the compiler will see the specialization and use that - otherwise, the compiler will use the primary template A. A similar pattern follows for the next 6 lines.

一梦浮鱼 2024-09-10 02:17:46

我将通过 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的存储方案都将是专门化的。希望这会有所帮助,至少有一点点。 :-)

I'm going to provide another answer in response to your comment with the Matrix example.

For your Matrix example, you can do this:

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

It takes on a similar pattern to my last answer. Now, all storage schemes taking on Dense will be specialized. Hope this helps, at least a little bit. :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文