假设你有这样的A类:
template <typename T, typename U>
class A;
Run Code Online (Sandbox Code Playgroud)
和B级这样:
template <typename T>
class B;
Run Code Online (Sandbox Code Playgroud)
现在你想要两个班级成为朋友,当T是同一类型时,这可能吗?
所以例如A<int, long>是朋友,B<int>而B<int>朋友在A<int, U>哪里U可以是任何类型.
有可能以某种方式使部分模板规范成为朋友类吗?即你认为你有以下模板类
template <class T> class X{
T t;
};
Run Code Online (Sandbox Code Playgroud)
现在你有部分特化,例如,指针
template <class T> class X<T*>{
T* t;
};
Run Code Online (Sandbox Code Playgroud)
我想做到的是,每一个可能X<T*>是朋友类X<S>为ANY S.即X<A*>应该是的朋友X<B>.
当然,我想到了X中通常的模板朋友声明:
template <class T> class X{
template <class S> friend class X<S*>;
}
Run Code Online (Sandbox Code Playgroud)
但是,这不能编译,g ++告诉我这个:
test4.cpp:34:15:错误:' template<class T> class X'的特化必须出现在命名空间范围内
test4.cpp:34:21:错误:部分特化' X<S*>'声明'朋友'
这根本不可能,还是有一些解决方法?
我之所以要问的是,我需要一个构造函数,X<T*>从任意X<S>(S必须是子类型T)创建这个类.
代码如下所示:
template <class T> class X<T*>{
T* t;
template<class S>
X(X<S> x) : t(&(x.t)) {} //Error, x.t …Run Code Online (Sandbox Code Playgroud) c++ templates partial-specialization template-specialization friend-class
根据[temp.class.order]§14.5.5.2,t在此示例中选择部分特化:
template< typename >
struct s { typedef void v, w; };
template< typename, typename = void >
struct t {};
template< typename c >
struct t< c, typename c::v > {};
template< typename c >
struct t< s< c >, typename s< c >::w > {};
t< s< int > > q;
Run Code Online (Sandbox Code Playgroud)
等效f于此示例中的重载选择:
template< typename >
struct s { typedef void v, w; };
template< typename, typename = void >
struct t {};
template< typename …Run Code Online (Sandbox Code Playgroud) c++ templates partial-specialization partial-ordering language-lawyer
当模板完全专用时,不需要复制成员函数.例如,在以下代码中,foo()只写入一次.
#include <iostream>
template<int M>
class B
{
public:
void foo();
private:
void header();
};
template<int M>
void
B<M>::foo()
{
// specialized code:
header();
// generic code:
std::cout << "M = " << M << std::endl;
}
template<int M>
void
B<M>::header()
{
std::cout << "general foo()" << std::endl;
}
template<>
void
B<2>::header()
{
std::cout << "special foo()" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是,对于部分特化,有必要复制类定义和所有成员函数.例如:
#include <iostream>
template<int M, int N>
class A
{
public:
void foo();
private:
void header();
};
template<int …Run Code Online (Sandbox Code Playgroud) 在"C++模板 - 完整指南 - 第二版"一书的第19.8.4章中,作者展示了如何在编译时确定类型是否为类类型:
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T, typename = void_t<>>
struct IsClass : false_type { };
template <typename T>
struct IsClass<T, void_t<int T::*>> : true_type { };
int main()
{
struct S { };
cout << IsClass<S>::value; // prints 1
}
Run Code Online (Sandbox Code Playgroud)
本段解释了部分特化如何检测类类型:
...只有类类型可以用作指向成员类型的基础.也就是说,在表单的类型构造中
X Y::*,Y只能是类类型.以下公式IsClass<T>利用属性(并int任意选择类型X)
我不明白为什么选择int作为X工作,即使我们测试IsClass<>一个S完全没有成员的结构(它也适用于具有其他成员的类类型int)
有模板类List.
template <typename Point>
class List
{
public:
template <const unsigned short N>
void load ( const char *file);
...
};
template <typename Point>
template <const unsigned short N>
void List <Point>::load ( const char *file)
}
Run Code Online (Sandbox Code Playgroud)
如何专门化N = 2的方法负载?此代码无效...
template <typename Point>
void List <Point> <2>::load ( const char *file)
{
}
Run Code Online (Sandbox Code Playgroud)
而且这段代码也行不通.
template <typename Point>
void List <Point> ::load <2> ( const char *file )
{
}
Error 3 error C2768: 'List<Point>::load' : illegal use of explicit template …Run Code Online (Sandbox Code Playgroud) 我有一个模板类的场景
template<typename X, typename Y>
class Foo
{
typedef Y::NestedType Bar;
int A (Bar thing);
void B();
int C(X that);
// other stuff
};
Run Code Online (Sandbox Code Playgroud)
然后我希望A()方法在X是给定类型时具有不同的行为(但是B和C可以保持不变,而实际代码实际上有大约10种其他方法,其中一些方法非常冗长,经常调整..所以我宁愿避免进行全班专业化并复制和粘贴完整的类实现)
我继续写道:
template<typename T>
int Foo<MyType, T>::A(Bar thing);
Run Code Online (Sandbox Code Playgroud)
但是我的编译器(clang 163.7.1)甚至拒绝将其视为任何类型的模板特化.
在我编写代码的方式中是否隐藏了一些语法错误,或者这种编码风格是无效的C++?不幸的是,即使其他编译器确实支持这个成语,我的公司仍然坚持使用clang.
感谢您的帮助.
c++ templates class partial-specialization template-specialization
这是这个问题的延续.如果成员类的部分特化是这样的,我特别感兴趣:
struct FooParent {
template <class>
struct Bar{ };
};
struct Foo: FooParent {
template <class T>
struct Bar<T*> {};
};
Run Code Online (Sandbox Code Playgroud)
我知道这可以在命名空间范围内完成:
template <class T>
struct Foo::Bar<T*>{ };
Run Code Online (Sandbox Code Playgroud)
但我也特别感兴趣的是派生类级别的类内部分特化.
clang和gcc在遇到前者时都会抱怨:
clang声明有明确的模板专业化,显然不会发生:
错误:类范围中'Bar'的显式特化
gcc在这里稍微冗长一点,并说成员模板的特化必须在命名空间范围内执行,这显然不是非派生类的情况.
错误:'template struct FooParent :: Bar'的特化必须出现在命名空间范围内
gcc是否在他的错误消息中?
c++ templates partial-specialization template-specialization language-lawyer
在为另一个问题创建这个答案时,我遇到了以下问题。考虑这个程序(godbolt):
#include <variant>
#include <iostream>
template <typename T>
struct TypeChecker {
void operator()() {
std::cout << "I am other type\n";
}
};
template<typename... Ts, template<typename...> typename V>
requires std::same_as<V<Ts...>, std::variant<Ts...>>
struct TypeChecker<V<Ts...>>
{
void operator()()
{
std::cout << "I am std::variant\n";
}
};
int main()
{
TypeChecker<std::variant<int, float>>{}();
TypeChecker<int>{}();
}
Run Code Online (Sandbox Code Playgroud)
输出(也是预期的)如下(使用 clang 14.0.0 以及 gcc 12.1):
I am std::variant
I am other type
Run Code Online (Sandbox Code Playgroud)
然而,如果模板的参数列表中的三个点被删除,就像这样(整个程序运行在godbolt上):
template<typename... Ts, template<typename> typename V>
Run Code Online (Sandbox Code Playgroud)
,那么 clang 和 gcc 的输出是不同的。clang …
c++ templates partial-specialization template-templates language-lawyer
我试图部分特化一个未模板类的模板化成员函数:
#include <iostream>
template<class T>
class Foo {};
struct Bar {
template<class T>
int fct(T);
};
template<class FloatT>
int Bar::fct(Foo<FloatT>) {}
int main() {
Bar bar;
Foo<float> arg;
std::cout << bar.fct(arg);
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
c.cc:14: error: prototype for ‘int Bar::fct(Foo<FloatT>)’ does not match any in class ‘Bar’
c.cc:9: error: candidate is: template<class T> int Bar::fct(T)
Run Code Online (Sandbox Code Playgroud)
如何修复编译器错误?
c++ templates partial-specialization template-specialization