考虑到我有一个简单的类模板:
template <typename T>
class foo
{
T t;
};
是否可以专门化foo
,使T
不是类型而是非类型值,以便:
foo<float> my_foo;
使用上面显示的类模板,而
foo<20> my_other_foo;
使用不同的模板专业化?这是可能的,如果是的话,模板专业化代码会是什么样的?
答案 0 :(得分:1)
这是可能的,如果是的话,部分专业化代码会是什么样的?
正如你想要的那样,不,这是不可能的。
但是,如果你可以使用C ++ 17,你可以做出几乎相反的事情:收到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 };
};
您可以专注于20
(其中20
是int
;不符合(例如)20L
或20U
)
template <>
struct foo<20>
{
static constexpr bool isSpecialized { true };
};
此解决方案的问题在于您不能拥有foo<float>
,因为float
值不能是模板非类型参数(因此您无法编写foo<0.0f>
,例如)。
您可以粗略地绕过此问题,添加第二个模板类型参数,其中包含默认值(第一个参数的类型)
template <auto Val, typename T = decltype(Val)>
struct bar
{
T t { Val };
static constexpr bool isSpecialized { false };
};
并且20
专业化仍然存在
template <>
struct bar<20>
{
static constexpr bool isSpecialized { true };
};
但现在您可以拨打bar<0, float>
来代替旧foo<float>
以下是完整的编译(显然是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
}
答案 1 :(得分: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;
}