使用 std::enable_if 元函数重载模板 class 中的运算符 +=
Overload operator += in template class with std::enable_if metafunction
我有一个字符串 class 作为 class 模板实现,例如:
template <class T>
class HGStringBasic
{
//...
public:
//...
HGStringBasic& operator += (const T* rhs)
{
//...
}
template <class U, std::enable_if_t<std::is_same<U, char>::value>* = nullptr>
HGStringBasic& operator += (const U* rhs)
{
//...
}
//...
}
代码符合 C++ 11 标准。
目标是实现一个重载运算符 += (const char) ,它仅在模板的 class T 为 "wchar_t".
时使用
我想知道,如果编译器不理解 C++11,我如何才能达到相同的结果。
更新:
对不起,我是 stackoverlow 的新手,我还没有看到我的代码没有完全显示在代码块中。到目前为止,我已经更新了我的代码。
我还纠正了模板函数运算符 += () 中模板参数列表中的错误,TartanLlama 你绝对正确,is_same<T, char>
必须是 is_same<U, char>
.
enable_if 不依赖于 C++11 功能。它在 boost 库中的 C++11 之前的实现方式几乎与现在的实现方式相同。这是取自 cppreference.com:
的可能实现
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
这在 C++11 之前的 C++ 中工作得很好。
首先,enable_if/is_same可以很容易地在C++2003中实现。例如,Boost 有它们,或者您可以自己创建它们——这是一个很好的做法。
其次,如果您不想使用 enable_if,您可以简单地为 w_char 提供 myString 的特化。为了减少编码量,将它放在一些基 class 中,从基 class 派生 myString 并提供基 class.
的特化
首先,您的 C++11 不 工作。如果我尝试这样做:
myString<int> x;
x += new int(4);
您的 operator+=
将无法编译。 SFINAE 仅适用于替换的 直接上下文 - 但 T
不在此处的直接上下文中,只有 U
是。所以正确的是:
template <class U,
class _T=T,
class = std::enable_if_t<std::is_same<_T, char>::value>>
myString& operator += (const U* rhs);
现在回到最初的问题。我们如何在 C++03 中编写以上内容?同样的想法。我们只是不能有默认的模板参数。但同样的原则适用:我们需要在直接上下文中替换失败:
template <typename T, typename U, typename R>
struct allow_for_char;
template <typename U, typename R>
struct allow_for_char<char, U, R> { typedef R type; };
然后您可以使用它来指定 return 类型:
template <class U>
typename allow_for_char<T, U, myString&>::type
operator += (const U* rhs);
现在我弄明白了,没有 c++11 和已知的元函数。非常感谢 Barry 提供的指定 return 类型的提示。
这是我所做的:
#include <type_traits>
template <class _ElemT>
class HGStringBasic
{
public:
// Append char* or wchar_t* depending on specialization
HGStringBasic& operator += (const _ElemT* rhs)
{
return *this;
}
// Allow char* if specialization is wchar_t
template <class U>
typename std::enable_if<std::is_same<U, char>::value, HGStringBasic&>::type operator += (const U* rhs)
{
// Convert ansistring to widestring
return *this;
}
// Allow wchar_t* if specialization is char
template <class U>
typename std::enable_if<std::is_same<U, wchar_t>::value, HGStringBasic&>::type operator += (const U* rhs)
{
// Convert widestring to ansistring
return *this;
}
};
我有一个字符串 class 作为 class 模板实现,例如:
template <class T>
class HGStringBasic
{
//...
public:
//...
HGStringBasic& operator += (const T* rhs)
{
//...
}
template <class U, std::enable_if_t<std::is_same<U, char>::value>* = nullptr>
HGStringBasic& operator += (const U* rhs)
{
//...
}
//...
}
代码符合 C++ 11 标准。 目标是实现一个重载运算符 += (const char) ,它仅在模板的 class T 为 "wchar_t".
时使用我想知道,如果编译器不理解 C++11,我如何才能达到相同的结果。
更新:
对不起,我是 stackoverlow 的新手,我还没有看到我的代码没有完全显示在代码块中。到目前为止,我已经更新了我的代码。
我还纠正了模板函数运算符 += () 中模板参数列表中的错误,TartanLlama 你绝对正确,is_same<T, char>
必须是 is_same<U, char>
.
enable_if 不依赖于 C++11 功能。它在 boost 库中的 C++11 之前的实现方式几乎与现在的实现方式相同。这是取自 cppreference.com:
的可能实现template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
这在 C++11 之前的 C++ 中工作得很好。
首先,enable_if/is_same可以很容易地在C++2003中实现。例如,Boost 有它们,或者您可以自己创建它们——这是一个很好的做法。
其次,如果您不想使用 enable_if,您可以简单地为 w_char 提供 myString 的特化。为了减少编码量,将它放在一些基 class 中,从基 class 派生 myString 并提供基 class.
的特化首先,您的 C++11 不 工作。如果我尝试这样做:
myString<int> x;
x += new int(4);
您的 operator+=
将无法编译。 SFINAE 仅适用于替换的 直接上下文 - 但 T
不在此处的直接上下文中,只有 U
是。所以正确的是:
template <class U,
class _T=T,
class = std::enable_if_t<std::is_same<_T, char>::value>>
myString& operator += (const U* rhs);
现在回到最初的问题。我们如何在 C++03 中编写以上内容?同样的想法。我们只是不能有默认的模板参数。但同样的原则适用:我们需要在直接上下文中替换失败:
template <typename T, typename U, typename R>
struct allow_for_char;
template <typename U, typename R>
struct allow_for_char<char, U, R> { typedef R type; };
然后您可以使用它来指定 return 类型:
template <class U>
typename allow_for_char<T, U, myString&>::type
operator += (const U* rhs);
现在我弄明白了,没有 c++11 和已知的元函数。非常感谢 Barry 提供的指定 return 类型的提示。
这是我所做的:
#include <type_traits>
template <class _ElemT>
class HGStringBasic
{
public:
// Append char* or wchar_t* depending on specialization
HGStringBasic& operator += (const _ElemT* rhs)
{
return *this;
}
// Allow char* if specialization is wchar_t
template <class U>
typename std::enable_if<std::is_same<U, char>::value, HGStringBasic&>::type operator += (const U* rhs)
{
// Convert ansistring to widestring
return *this;
}
// Allow wchar_t* if specialization is char
template <class U>
typename std::enable_if<std::is_same<U, wchar_t>::value, HGStringBasic&>::type operator += (const U* rhs)
{
// Convert widestring to ansistring
return *this;
}
};