我错误地认为template
中的class
函数只有在被调用时才被实例化。请参阅以下简单代码:
template<typename T>
struct A
{
T *p;
T& operator * () { return *p; }
};
int main ()
{
A<int> ai; // ok
int i = *ai; // works fine
A<void> av; // compiler complains even "*av" is not called
}
在声明A<void>
时,编译错误为:
error: forming reference to void
我尝试将模板外的void
功能专门化,如下所示:
template<>
void A<void>::operator * () {}
但它没有帮助,并给出错误:
error: no member function ‘operator*’ declared in ‘A<void>’
有没有办法用C ++ 03解决这个问题?
答案 0 :(得分:5)
怎么样?
template < typename T >
struct ReferenceOrVoid
{ typedef T& Value; };
template < >
struct ReferenceOrVoid < void >
{ typedef void Value; };
template<typename T>
struct A
{
T *p;
typename ReferenceOrVoid < T > :: Value
operator * () { return *p; }
};
当然,在A
为T
的情况下,这取决于您希望void
的行为。当然,您还可以为A
专门化整个void
结构。
答案 1 :(得分:3)
我认为只要为void
赋予函数不同的返回类型就足够了:
template <typename T>
struct is _void {
enum { value = false };
};
template <>
struct is_void<> {
enum { value = true };
};
struct A {
...
typename enable_if<!is_void<T::value>, T&>::type
operator*() {
...
}
};
由于仍然可以检查签名,因此您可能需要使用条件类型,例如,在使用void
实例化时将其设为void
:
template <bool, typename T1, typename>
struct conditional {
typedef T1 type;
};
template <typename T1, typename T2>
struct conditional<false, T1, T2> {
typedef T2 type;
};
答案 2 :(得分:3)
函数的签名将被实例化,函数体不会。无论您是否使用该函数,T
都会在整个类定义中被替换。请注意:
template<typename T>
struct A
{
T *p;
T *operator * () { return p->aklsdjlkasjd(); }
};
int main ()
{
A<void> av;
}
将编译,因为您没有使用operator*
。