我使用C#已有很长时间了,我对C ++中的函数模板有一些疑问。
template <typename T>
T max(T x, T y)
{
return (x > y) ? x : y;
}
Run Code Online (Sandbox Code Playgroud)
typename使用某些示例而使用其他示例class?有什么不同?T到特定类型,或从特定类型派生的类型?更新:
我很感谢所有答案,但是其中一些包含了一些示例,当我尝试将其应用于我的代码时,这些示例将不会编译。
为了澄清问题3,我有以下方法:
template<typename T>
std::unique_ptr<T> ExecuteSqlQuery(LPCTSTR pszSqlQuery, UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE);
Run Code Online (Sandbox Code Playgroud)
我想声明使用CRecordsetas 的此变量的变体T,以使以下任一语句均有效:
auto result = db.ExecuteSqlQuery<CCustomerRecordset>(L"SELECT ...");
auto result = db.ExecuteSqlQuery(L"SELECT ...");
Run Code Online (Sandbox Code Playgroud)
为什么在模板参数声明中
typename使用某些示例而使用其他示例class?有什么不同?
模板参数声明中的两者没有什么区别,但是在其他情况下,它们都有其他单独的含义。例如typename,用于将从属名称标记为类型名称,class并用于引入类声明。
有什么方法可以将T限制为特定类型,或从特定类型派生的类型?
是的,一种方法是依靠SFINAE放弃满足某些条件的类型的实例化,通常由来促进std::enable_if,例如(使用C ++ 14):
template<typename T, typename = std::enable_if_t<std::is_base_of_v<SomeBaseClass, T>>
T max(T x, T y)
{
return (x > y) ? x : y;
}
Run Code Online (Sandbox Code Playgroud)
在即将发布的C ++ 20中,将支持Concepts,使您可以编写
template<std::DerivedFrom<SomeBaseClass> T>
T max(T x, T y)
{
return (x > y) ? x : y;
}
Run Code Online (Sandbox Code Playgroud)
一个类是否可以通过两种方法使用相同的名称,但一种方法是模板化的,而另一种则不是?
是的,这是可能的。在过载解决方案中,如果两个候选者都具有相同的匹配性,则首选非模板化者。
template<typename T> T foo(T x); //< no implementation in the generic case
template<> T foo<float>(T x) { return x; } //< float is allowed
template<> T foo<double>(T x) { return x; } //< double is allowed
Run Code Online (Sandbox Code Playgroud)
您也可以处理派生类型(有几种方法可以做到这一点)
#include <string>
#include <iostream>
struct Cow {};
template<typename T>
struct Moo
{
// default to false
template<bool valid = std::is_base_of<Cow, T>::value>
static void moo()
{
std::cout << "No moo for you!" << std::endl;
}
// moo if T is a cow
template<>
static void moo<true>()
{
std::cout << "Mooooo!" << std::endl;
}
};
struct AberdeenAngus : public Cow {};
struct Sheep {};
int main()
{
Moo<AberdeenAngus>::moo();
Moo<Sheep>::moo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
class Foo
{
public:
template<typename T>
T thing(T a) { return a; } //< template
float thing(float a) { return a * 5.0f; } //< function overload
};
Run Code Online (Sandbox Code Playgroud)
为什么在模板参数声明中有些示例使用
typename而其他示例使用class?有什么不同?
从历史上看,
只typename允许用于简单模板,并且class应该用于模板模板参数:
template <template <typename> class C> void foo();
Run Code Online (Sandbox Code Playgroud)
使用如
foo<std::unique_ptr>();
Run Code Online (Sandbox Code Playgroud)
现在 (C++17) 在这些上下文中是可互换的。
有没有办法限制
T到特定类型,或限制到从特定类型派生的类型?
你可以用SFINAE(它有几种语法)来做到这一点,在 C++20 中用Concepts来做到这一点。
template <typename T>
std::enable_if_t<some_trait<T>::value> foo();
Run Code Online (Sandbox Code Playgroud)
有没有办法让一个类有两个同名的方法,除了一个是模板化的,另一个不是?
是的,你可能有几个这样的重载
template <template <class> typename C> void foo();
template <int> void foo();
void foo();
Run Code Online (Sandbox Code Playgroud)
或者更简单
template <typename T> void foo(T); // #1
void foo(int); // #2
// Note that foo<int> (#1 with T = int) is different than foo (#2)
Run Code Online (Sandbox Code Playgroud)