简体   繁体   English

非类型的模板专业化

[英]Template specialization with non-type

Considering I have a simple class template: 考虑到我有一个简单的类模板:

template <typename T>
class foo
{
    T t;
};

Is it possible to specialize foo such that T is not a type but a non-type value so that: 是否可以专门化foo使得T不是类型而是非类型值,因此:

foo<float> my_foo;

Uses the class template shown above, while 使用上面显示的类模板,而

foo<20> my_other_foo;

Uses a different template specialization? 使用不同的模板专业化? Is this possible, and if yes, what would the template specialization code look like? 这是可能的,如果是的话,模板专业化代码会是什么样的?

Is this possible, and if yes, what would the partial specialization code look like? 这是可能的,如果是的话,部分专业化代码会是什么样的?

As you exactly want, no: it's impossible. 正如你想要的那样,不,这是不可能的。

But, if you can use C++17, you can make almost the contrary: receiving an auto value ( T become the declval() of the value) 但是,如果你可以使用C ++ 17,你可以做出几乎相反的declval() :接收一个auto值( T成为值的declval()

template <auto Val>
struct foo
 {
   using T = decltype(Val);

   T t { Val }; // or also decltype(Val) t {Val};

   static constexpr bool isSpecialized { false };
 };

you can specialize for 20 (where 20 is an int ; doesn't match (by example) 20L or 20U ) 你可以专门为20 (其中20是一个int ;不匹配(例如) 20L20U

template <>
struct foo<20>
 {
   static constexpr bool isSpecialized { true };
 };

The problem of this solution is that you can't have foo<float> because a float value can't be a template not-type parameter (so you can't write foo<0.0f> , by example). 这个解决方案的问题是你不能有foo<float>因为float值不能是模板not-type参数(所以你不能写foo<0.0f> ,例如)。

You can roughly bypass this problem adding a second template type parameter with a default value (the type of the first parameter) 你可以大致绕过这个问题,添加第二个模板类型参数与默认值(第一个参数的类型)

template <auto Val, typename T = decltype(Val)>
struct bar
 {
   T t { Val };

   static constexpr bool isSpecialized { false };
 };

and the 20 specialization remain 20专业化仍然存在

template <>
struct bar<20>
 {
   static constexpr bool isSpecialized { true };
 };

but now you can call bar<0, float> as substitute of the old foo<float> 但现在你可以调用bar<0, float>代替旧的foo<float>

The following is a full compiling (C++17, obviously) example 以下是完整的编译(显然是C ++ 17)示例

#include <iostream>

template <auto Val>
struct foo
 {
   using T = decltype(Val);

   T t { Val }; // or also decltype(Val) t {Val};

   static constexpr bool isSpecialized { false };
 };

template <>
struct foo<20>
 {
   static constexpr bool isSpecialized { true };
 };

template <auto Val, typename T = decltype(Val)>
struct bar
 {
   T t { Val };

   static constexpr bool isSpecialized { false };
 };

template <>
struct bar<20>
 {
   static constexpr bool isSpecialized { true };
 };

int main ()
 {
   std::cout << foo<0>::isSpecialized << std::endl;   // print 0
   std::cout << foo<20>::isSpecialized << std::endl;  // print 1
   std::cout << foo<20L>::isSpecialized << std::endl; // print 0

   std::cout << bar<0>::isSpecialized << std::endl;         // print 0
   std::cout << bar<20>::isSpecialized << std::endl;        // print 1
   std::cout << bar<20L>::isSpecialized << std::endl;       // print 0
   std::cout << bar<20, float>::isSpecialized << std::endl; // print 0

 }
#include <type_traits>
#include <iostream>

template <typename T>
struct foo
{
    foo(T x) : t(x) {};

    T t;
};

// specialise for integral constant
template<class T, T N>
struct foo<std::integral_constant<T, N>>
{
    // same interface
    static constexpr T t = N;
};

// test
int main()
{
    auto foo1 = foo<float>(10.0);
    auto foo2 = foo<std::integral_constant<int, 20>>();

    std::cout << foo1.t << std::endl;
    std::cout << foo2.t << std::endl;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM