我想知道是否有类似的东西是可能的.基本上,我有一个模板化的类偶尔会接受模板类的对象.我想专门为它(或只是一个成员函数)的特定模板类,但该类的"通用"形式.
template<typename T, typename S>
class SomeRandomClass
{
//put something here
};
template<typename T>
class MyTemplateClass
{
void DoSomething(T & t) {
//...something
}
};
template<>
void MyTemplateClass< SomeRandomClass<???> >::DoSomething(SomeRandomClass<???> & t)
{
//something specialized happens here
}
Run Code Online (Sandbox Code Playgroud)
用适当的类型(double等)替换问号是有效的,但我希望它保持通用.我不知道该放什么,因为任何类型都没有定义.我环顾四周,了解了模板模板参数,尝试了各种组合无济于事.谢谢您的帮助!
Rya*_*oun 24
可以像这样专门化这个类
template <>
template <typename T,typename S>
class MyTemplateClass <SomeRandomClass<T,S> >
{
void DoSomething(SomeRandomClass<T,S>& t) { /* something */ }
};
Run Code Online (Sandbox Code Playgroud)
仅仅专门化成员方法是不可能的,因为专门化作为一个整体在类上,你必须定义一个新类.但是,你可以这样做
template <>
template <typename T,typename S>
class MyTemplateClass <SomeRandomClass<T,S> >
{
void DoSomething(SomeRandomClass<T,S>& t);
};
template <>
template <typename T,typename S>
void MyTemplateClass<SomeRandomClass<T,S> >::DoSomething(SomeRandomClass<T,S>& t)
{
// something
}
Run Code Online (Sandbox Code Playgroud)
分割声明和定义.
And*_*dyG 21
我不完全确定为什么@Ryan Calhoun 专注于他的方式,但这是一个更简洁的例子:
// class we want to specialize with later on
template<typename T, typename S>
struct SomeRandomClass
{
int myInt = 0;
};
// non-specialized class
template<typename T>
struct MyTemplateClass
{
void DoSomething(T & t)
{
std::cout << "Not specialized" << std::endl;
}
};
// specialized class
template<typename T, typename S>
struct MyTemplateClass< SomeRandomClass<T, S> >
{
void DoSomething(SomeRandomClass<T,S> & t)
{
std::cout << "Specialized" << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
您可以看到您不需要在接受的答案中使用冗余语法:
template<>
template<typename T, typename S>
Run Code Online (Sandbox Code Playgroud)
您可以在非专业类中使用type_traits和tag-dispatch来专门化该函数.
让我们首先提出一个概念is_random_class:
// concept to test for whether some type is SomeRandomClass<T,S>
template<typename T>
struct is_random_class : std::false_type{};
template<typename T, typename S>
struct is_random_class<SomeRandomClass<T,S>> : std::true_type{};
Run Code Online (Sandbox Code Playgroud)
然后让我们MyTemplateClass再次声明我们,但这次没有模板化(因为我们没有专门化)所以我们称之为MyNonTemplatedClass:
class MyNonTemplatedClass
{
public:
template<typename T>
void DoSomething(T & t)
{
DoSomethingHelper(t, typename is_random_class<T>::type());
}
// ...
Run Code Online (Sandbox Code Playgroud)
注意DoSomething现在是如何模板化的,它实际上是在调用助手而不是实现逻辑本身?
让我们分解一下:
DoSomethingHelper(t, typename is_random_class<T>::type());
Run Code Online (Sandbox Code Playgroud)
t是以前的; 我们正在传递类型的论点T&typename is_random_class<T>::type()
is_random_class<T>是我们的概念,因为它源于std::true_type或者std::false_type它将::type在类中定义(谷歌的"类型特征")::type()'实例化'指定的类型is_random_class<T>::type.我用引号说出来,因为我们真的会把它扔掉,就像我们后面看到的那样typename是必需的,因为编译器不知道is_random_clas<T>::type实际命名类型.现在我们准备好了解其余部分MyNonTemplatedClass:
private:
//use tag dispatch. If the compiler is smart it won't actually try to instantiate the second param
template<typename T>
void DoSomethingHelper(T&t, std::true_type)
{
std::cout << "Called DoSomething with SomeRandomClass whose myInt member has value " << t.myInt << std::endl;
}
template<typename T>
void DoSomethingHelper(T&t, std::false_type)
{
std::cout << "Called DoSomething with a type that is not SomeRandomClass\n";
}
};
Run Code Online (Sandbox Code Playgroud)
请注意,我们的辅助函数名称相同,但在第二个参数的类型上重载.我们没有为参数命名,因为我们不需要它,并且希望编译器在仍然调用正确函数的同时优化它.
我们的概念强制DoSomethingHelper(T&t, std::true_type)只有T类型SomeRandomClass,并调用另一种类型.
标签分派的主要好处是,如果您只想专门化该类中的单个函数,则不需要专门化整个类.
标记调度将在编译时发生,如果您尝试仅在DoSomething函数内对概念执行分支,则无法获得.
Jas*_*son 10
您需要做的只是模拟您想要保持通用的内容.以你的开始:
template<typename T, typename S>
void MyTemplateClass< SomeRandomClass<T,S> >::DoSomething(SomeRandomClass<T,S> & t)
{
//something specialized happens here
}
Run Code Online (Sandbox Code Playgroud)
编辑:
或者,如果您只想保留SomeRandomClass通用的一部分,您可以:
template<typename T>
void MyTemplateClass< SomeRandomClass<T,int> >::DoSomething(SomeRandomClass<T,int> & t)
{
//something specialized happens here
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13226 次 |
| 最近记录: |