C++ 模板化类专门化,其中模板参数是模板
我想知道类似的事情是否可能发生。基本上,我有一个模板类,它偶尔会获取模板类的对象。我想为一个特定的模板化类专门化它(或者只是一个成员函数),但是该类的“泛型”形式C++ 模板化类专门化,其中模板参数是模板,c++,templates,C++,Templates,我想知道类似的事情是否可能发生。基本上,我有一个模板类,它偶尔会获取模板类的对象。我想为一个特定的模板化类专门化它(或者只是一个成员函数),但是该类的“泛型”形式 template<typename T, typename S> class SomeRandomClass { //put something here }; template<typename T> class MyTemplateClass { void DoSomething(T &a
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
}
模板
课堂
{
//放点东西在这儿
};
模板
类MyTemplateClass
{
无效剂量测定(T&T){
//……什么
}
};
模板
void MyTemplateClass:DoSomething(SomeRandomClass&t)
{
//这里发生了一些特殊的事情
}
用适当的类型(双精度等)替换问号是可行的,但我希望它保持通用性。我不知道该放什么,因为任何类型都不会被定义。我环顾四周,了解了模板参数,并尝试了各种组合,但都无济于事。谢谢你的帮助 你所需要做的只是在你想保持通用性的基础上建立模板。以您开始的内容为例:
template<typename T, typename S>
void MyTemplateClass< SomeRandomClass<T,S> >::DoSomething(SomeRandomClass<T,S> & t)
{
//something specialized happens here
}
编辑:这是对不同问题的正确回答 两次使用typename
T
会稍微混淆这个问题,因为它们是单独编译的,并且没有任何连接
您可以重载该方法以获取模板参数:
template <typename T>
class MyTemplateClass
{
void DoSomething(T& t) { }
template <typename U,typename V>
void DoSomething(SomeRandomClass<<U,V>& r) { }
};
模板化调用将被选择为匹配重载,而无需显式重新指定类型
编辑:
使用模板专门化对DoSomething
的过载没有影响。如果你把这个类专门化如下
template <>
class SomeRandomClass <int,double>
{
// something here...
};
模板
课堂
{
//这里有些东西。。。
};
然后,上面的重载将很高兴地耗尽这个专门的实现。只需确保专用模板和默认模板的接口匹配即可
如果您想要专门化
DoSomething
以获取SomeRandomClass
的特定类型对,那么您已经失去了通用性…这就是专门化的含义。可以像这样专门化类
template <>
template <typename T,typename S>
class MyTemplateClass <SomeRandomClass<T,S> >
{
void DoSomething(SomeRandomClass<T,S>& t) { /* something */ }
};
模板
模板
类MyTemplateClass
{
void DoSomething(SomeRandomClass&t){/*someone*/}
};
不可能只对成员方法进行专门化,因为专门化是作为一个整体对类进行的,您必须定义一个新类。但是,你可以这样做
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
}
模板
模板
类MyTemplateClass
{
无效剂量测定(等级&t);
};
模板
模板
void MyTemplateClass::DoSomething(SomeRandomClass&t)
{
//某物
}
将声明和定义分开。我不完全确定为什么@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;
}
};
然后让我们再次声明我们的MyTemplateClass
,但是这次没有模板化(因为我们没有专门化),所以我们将其称为MyNonTemplatedClass
:
// 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{};
class MyNonTemplatedClass
{
public:
template<typename T>
void DoSomething(T & t)
{
DoSomethingHelper(t, typename is_random_class<T>::type());
}
// ...
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";
}
};
与以前一样;我们正在传递类型为t
T&
typename是\u random\u class::type()
是我们的概念,因为它源于is_random_class
或std::true_type
,它将在类中定义一个std::false_type
(谷歌的“类型特征”)::type
“实例化”由::type()
。我用引号把它说出来,因为我们真的要把它扔掉,就像我们后面看到的那样指定的类型是\u random\u class::type
是必需的,因为编译器不知道typename
实际命名类型是\u random\u clas::type
// 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{};
class MyNonTemplatedClass
{
public:
template<typename T>
void DoSomething(T & t)
{
DoSomethingHelper(t, typename is_random_class<T>::type());
}
// ...
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";
}
};
然后,我们在只编译适当分支的if constexpr
表达式中使用它(并在编译时丢弃另一个分支,因此检查在编译时进行,而不是在运行时进行):
如果要使用提供模板结构作为模板参数(打算在内部使用),而不需要对其进行专门化,请执行以下操作: 下面是一个示例,它将类型作为模板参数附加到给定模板sfinae结构的元组中:
template<typename Tuple, typename T, template<typename> class /*SFINAEPredicate*/>
struct append_if;
template<typename T, template<typename> class SFINAEPredicate, typename ... Types>
struct append_if<std::tuple<Types...>, T, SFINAEPredicate>
{
using type = typename std::conditional<SFINAEPredicate<T>::value,
std::tuple<Types..., T>, std::tuple<Types...>>::type;
};
// usage
using tuple_with_int = append_if<std::tuple<>, int, std::is_fundamental>;
模板
结构append_if;
模板
结构附加\u如果
{
使用type=typename std::conditional::type;
};
//用法
使用tuple_和_int=append_if;
这可以从C++11开始使用。不完全是这样。这看起来只是DoSomething成员的重载,而不是类本身的专门化。你是对的,但不管你是传递专门化类还是常规模板,方法重载都没有区别。我终于明白你的要求了。这个答案完全是反向的。我想差不多就是这样,但是我无法编译(使用g++或intel)。我认为,将模板放在那里会使编译器混淆,不认识到这是一种专门化(即需要有一个模板,对吗?),如果在2010年您希望您的代码在rhel4和rhel5上使用gcc进行编译,并在windows xp上使用visual studio 2008进行编译,这也是你编写它的方式。你能用同样的方式专门化模板函数吗?@Mirco只是一个裸函数,不是类的一部分?对于这种情况,您实际上不需要初始的空模板,因为您没有要专门化的包含模板类我想专门针对所有类型,比如std::list类型。我可以获得类似于
模板std::list fun(void){/*return sth*/}代码>?仅专门针对退货类型?我不确定这样的部分专业化是否被允许。但这将是一个很好的问题,张贴和得到答案。
template<class T>
constexpr bool is_random_class_v = is_random_class<T>::value;
struct MyNonTemplatedClass
{
template<class T>
void DoSomething(T& t)
{
if constexpr(is_random_class_v<T>)
std::cout << "Called DoSomething with SomeRandomClass whose myInt member has value " << t.myInt << std::endl;
else
std::cout << "Called DoSomething with a type that is not SomeRandomClass\n";
}
};
struct MyNonTemplatedClass
{
template<class T> requires is_random_class_v<T>
void DoSomething(T& t)
{
std::cout << "Called DoSomething with SomeRandomClass whose myInt member has value " << t.myInt << std::endl;
}
template<class T> requires !is_random_class_v<T>
void DoSomething(T&)
{
std::cout << "Called DoSomething with a type that is not SomeRandomClass\n";
}
};
template<typename Tuple, typename T, template<typename> class /*SFINAEPredicate*/>
struct append_if;
template<typename T, template<typename> class SFINAEPredicate, typename ... Types>
struct append_if<std::tuple<Types...>, T, SFINAEPredicate>
{
using type = typename std::conditional<SFINAEPredicate<T>::value,
std::tuple<Types..., T>, std::tuple<Types...>>::type;
};
// usage
using tuple_with_int = append_if<std::tuple<>, int, std::is_fundamental>;