我想定义一个模板类,其模板参数将始终是一个整数类型.该类将包含两个成员,一个是类型,另一个是类型T的无符号变体T- 即if T == int,then T_Unsigned == unsigned int.我的第一直觉是这样做:
template <typename T> class Range {
typedef unsigned T T_Unsigned; // does not compile
public:
Range(T min, T_Unsigned range);
private:
T m_min;
T_Unsigned m_range;
};
Run Code Online (Sandbox Code Playgroud)
但它不起作用.然后我考虑使用部分模板专业化,如下所示:
template <typename T> struct UnsignedType {}; // deliberately empty
template <> struct UnsignedType<int> {
typedef unsigned int Type;
};
template <typename T> class Range {
typedef UnsignedType<T>::Type T_Unsigned;
/* ... */
};
Run Code Online (Sandbox Code Playgroud)
只要您UnsignedType对每个整数类型进行部分专门化,这都可以.这是一些额外的复制粘贴工作(削减明智地使用宏),但可以使用. …
// #1
template <typename T, T n1, T n2>
struct foo {
static const char* scenario() {
return "#1 the base template";
}
};
// #2
// partial specialization where T is unknown and n1 == n2
template <typename T, T a>
struct foo<T, a, a> {
static const char* scenario() {
return "#2 partial specialization";
}
};
Run Code Online (Sandbox Code Playgroud)
下面的主要内容在g ++(6.1)和clang ++(3.8.0)上有不同的结果:
extern const char HELLO[] = "hello";
double d = 2.3;
int main() {
cout << foo<int, 1, 2> …Run Code Online (Sandbox Code Playgroud) c++ templates partial-specialization template-specialization
在看这个问题的时候,我发现自己在cpp参考站点,我发现了一个奇怪的新手语法:
template<class Ret, class... Args>
struct is_function<Ret(Args......)volatile &&> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
是的,6个点!最初我认为这是一个拼写错误,但在再次检查libstdc ++ 源之后,例如在第444行:
template<typename _Res, typename... _ArgTypes>
struct is_function<_Res(_ArgTypes......) volatile &&> : public true_type { };
Run Code Online (Sandbox Code Playgroud)
这是一个有效的语法吗?点点,用于打包和解包参数包?6个点做什么?
在下一个程序中,结构模板A<int>有一个专门化A<char>:
template <int>
struct A { constexpr operator int() { return 1; } };
template <char c>
struct A<c> { constexpr operator int() { return 2; } };
int main() {
static_assert( A<1000>{} == 1 ); //ok in Clang and GCC
static_assert( A<1>{} == 2 ); //ok in Clang only
}
Run Code Online (Sandbox Code Playgroud)
A<1>{}.error C2753: 'A<c>': partial specialization cannot match argument list for primary template
Run Code Online (Sandbox Code Playgroud)
演示: https: //gcc.godbolt.org/z/Ef95jv5E5
这里是哪个编译器?
我不明白为什么主要陈述含糊不清.
template<class T, class U, int I> struct X
{ void f() { cout << "Primary template" << endl; } };
template<class T, int I> struct X<T, T*, I>
{void f() { cout << "Partial specialization 1" << endl;}};
template<class T, class U, int I> struct X<T*, U, I>
{void f() { cout << "Partial specialization 2" << endl;}};
template<class T> struct X<int, T*, 10>
{void f() { cout << "Partial specialization 3" << endl;}};
template<class T, class U, int …Run Code Online (Sandbox Code Playgroud) c++ templates partial-specialization specialization template-specialization
正如大多数C++程序员应该知道的那样,不允许对自由函数进行部分模板特化.例如,以下是非法的C++:
template <class T, int N>
T mul(const T& x) { return x * N; }
template <class T>
T mul<T, 0>(const T& x) { return T(0); }
// error: function template partial specialization ‘mul<T, 0>’ is not allowed
Run Code Online (Sandbox Code Playgroud)
然而,类/结构的模板偏特是允许的,并且可以被利用来模仿的自由功能模板偏特的功能.例如,最后一个示例中的目标目标可以通过以下方式实现:
template <class T, int N>
struct mul_impl
{
static T fun(const T& x) { return x * N; }
};
template <class T>
struct mul_impl<T, 0>
{
static T fun(const T& x) { return T(0); }
};
template …Run Code Online (Sandbox Code Playgroud) 部分模板专业化是C++中通用编程最重要的概念之一.例如:实现通用交换功能:
template <typename T>
void swap(T &x, T &y) {
const T tmp = x;
y = x;
x = tmp;
}
Run Code Online (Sandbox Code Playgroud)
专门用于支持O(1)交换的向量:
template <typename T, class Alloc>
void swap(vector<T, Alloc> &x, vector<T, Alloc> &y) { x.swap(y); }
Run Code Online (Sandbox Code Playgroud)
因此,当您在泛型函数中调用swap(x,y)时,总能获得最佳性能;
非常感谢,如果您可以在替代语言中发布等效语言(或语言的部分专业化的规范示例,如果语言不支持交换概念).
编辑:所以看起来许多回答/评论的人真的不知道什么是部分专业化,而且通用交换示例似乎妨碍了某些人的理解.一个更一般的例子是:
template <typename T>
void foo(T x) { generic_foo(x); }
Run Code Online (Sandbox Code Playgroud)
部分专业化将是:
template <typename T>
void foo(vector<T> x) { partially_specialized_algo_for_vector(x); }
Run Code Online (Sandbox Code Playgroud)
完整的专业化将是:
void foo(vector<bool> bitmap) { special_algo_for_bitmap(bitmap); }
Run Code Online (Sandbox Code Playgroud)
为什么这很重要?因为你可以在泛型函数中调用foo(任何东西):
template <typename T>
void bar(T x) {
// stuff...
foo(x);
// …Run Code Online (Sandbox Code Playgroud) language-agnostic generics programming-languages partial-specialization
陷入另一个模板问题:
问题:我想在对象是指针的情况下部分地专门化一个容器类(foo),并且我只想专门使用delete-method.应该是这样的:
lib代码
template <typename T>
class foo
{
public:
void addSome (T o) { printf ("adding that object..."); }
void deleteSome (T o) { printf ("deleting that object..."); }
};
template <typename T>
class foo <T *>
{
public:
void deleteSome (T* o) { printf ("deleting that PTR to an object..."); }
};
Run Code Online (Sandbox Code Playgroud)
用户代码
foo<myclass> myclasses;
foo<myclass*> myptrs;
myptrs.addSome (new myclass());
Run Code Online (Sandbox Code Playgroud)
这导致编译器告诉我myptrs没有一个名为addSome的方法.为什么?
感谢名单.
LIB
template <typename T>
class foobase
{
public:
void addSome (T o) { printf …Run Code Online (Sandbox Code Playgroud) 我正在尝试定义部分专门化的类模板的成员函数,但是不同的编译器对我可以做什么以及为什么有截然不同的看法。
让我们慢慢来,从适用于所有主要编译器(all = gcc、clang 和 msvc)的东西开始:
#include <concepts>
#include <type_traits>
template <class T>
concept Integer
= std::is_same_v<T,int> || std::is_same_v<T,unsigned int>;
template <class T>
concept FloatingPoint
= std::is_same_v<T,float> || std::is_same_v<T,double>;
template <class T>
struct Foo
{
T get() {return 0;}
};
template <Integer T>
struct Foo<T>
{
T get(){ return 0; }
};
template <FloatingPoint T>
struct Foo<T>
{
T get(){ return 0; }
};
int main()
{
Foo<char>().get();
Foo<int>().get();
Foo<float>().get();
}
Run Code Online (Sandbox Code Playgroud)
很酷,但我想将成员函数的声明和定义分开。让我们将定义移到专门的类之一 …
c++ partial-specialization visual-c++ language-lawyer c++-concepts
以下代码
#include <iostream>
#include <utility>
template<typename F, typename... T>
struct Wrapper{ };
template<typename T>
struct is_wrapper : std::false_type {};
template<typename... T>
struct is_wrapper<Wrapper<T...>> : std::true_type {};
//template<typename F, typename... T>
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {};
int main()
{
Wrapper<int, double> w;
std::cout << is_wrapper<decltype(w)>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
打印0.但是,如果取消注释中间的两行,则打印1.
为什么不总是打印1?第二部分专业化是否也应该涵盖显然仅由第三(评论)部分专业化所涵盖的案例?
c++ ×9
templates ×5
c++11 ×2
c++-concepts ×1
c++14 ×1
generics ×1
traits ×1
unsigned ×1
visual-c++ ×1