cpp03如何实现条件隐式转换?

问题描述 投票:0回答:2

示例:

#include <cstdio>

class Dummy {};

template<typename T>
class IsDummy { public: enum { Value = 0, }; };
template<>
class IsDummy<Dummy> { public: enum { Value = 1, }; };

template<typename T, int isDummy = IsDummy<T>::Value>
class Wrapper { };
template<typename T>
class Wrapper<T, 1> {
public:
    typedef T Value;
};

static void func(Dummy *) {}
static void func(const char *) {}

class Object0 {
public:
    template<typename T>
    operator T *(void) const {return NULL;}
};

class Object1 {
public:
    template<typename T>
    operator typename Wrapper<T>::Value *(void) const {return NULL;}
};

int main(int argc, char **argv)
{
    Object0 o0;
    func(o0);  // <= ambiguous
    Object1 o1;
    func(o1);  // <= no matching function
    return 0;
}

我想做的事:

  • 使
    func(o0)
    func(o1)
    仅匹配
    func(Dummy *)
    (以及
    IsDummy<>
    专门化的任何其他类),但不适用于
    func(const char *)
  • 兼容cpp03(不支持函数的部分特化(
    operator T()
    函数))

发生了什么:

  • func(o0)
    会导致
    ambiguous
  • func(o1)
    会导致
    no matching function
c++ c++03
2个回答
0
投票

我认为两个问题:

  1. Object0 o0
    是一个对象而不是指针,您应该使用
    func(&o0)
    ,也适用于
    Object o1
  2. Object0*
    不能自动/隐式转换为
    Dummy*
    const char&
    ,您应该指定
    func(Object0*)
    或使
    Object0
    Dummy*
    派生(将派生类转换为基类可能会丢失一些功能)。
class Object0: public Dummy {...}
func(&o0); // Object* -> Dummy* (candidate because convertible)

0
投票

T
不能从
typename Wrapper<T>::Value
推出。在考虑模板化转换运算符时,如果无法推断出任何模板参数(从默认参数或目标类型),则无法调用转换运算符。

你必须使

T
可推论。为了避免转换为其他指针类型,请使用 SFINAE 禁用无效
T
的转换运算符。

在C++11中,你可以这样做:

class Object1 {
public:
    template<typename T, typename std::enable_if<IsDummy<T>::Value>::type* = nullptr>
    operator T *(void) const {return nullptr;}
};

但是,C++03 中不存在默认模板参数。您无法更改返回类型,因为

operator std::enable_if_t<IsDummy<T>::value, T*>
也是不可推论的。转换运算符也不接受非对象参数。

剩下一个位置:动态异常规范:

class Object1 {
public:
    template<typename T>
    operator T *(void) throw(typename std::enable_if<IsDummy<T>::Value, void*>::type) const {return NULL;}
};

std::enable_if
相对容易实现,但这也有一个缺点,现在你的操作员有一个动态异常规范)

© www.soinside.com 2019 - 2024. All rights reserved.