首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >转换运算符模板专门化

转换运算符模板专门化
EN

Stack Overflow用户
提问于 2011-10-12 22:18:46
回答 2查看 7.3K关注 0票数 20

这是一个理解转换运算符、模板和模板专门化的主要学术练习。以下代码中的转换运算符模板适用于intfloatdouble,但在与std::string一起使用时会失败...说大也大吧。我已经创建了到std::string的转换的专门化,它在与初始化std::string s = a;一起使用时有效,但在与强制转换static_cast<std::string>(a)一起使用时失败。

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <sstream>

class MyClass {
     int y;
public:
    MyClass(int v) : y(v) {}
    template <typename T>
    operator T() { return y; };
};

template<>
MyClass::operator std::string() {
    std::stringstream ss;
    ss << y << " bottles of beer.";
    return ss.str();
}

int main () {
    MyClass a(99);
    int i    = a;
    float f  = a;
    double d = a;
    std::string s = a;

    std::cerr << static_cast<int>(a) << std::endl;
    std::cerr << static_cast<float>(a) << std::endl;
    std::cerr << static_cast<double>(a) << std::endl;
    std::cerr << static_cast<std::string>(a) << std::endl; // Compiler error
}

上面的代码在g++和icc中生成了一个编译器错误,两者都抱怨没有用户定义的转换适合于将MyClass实例转换为static_cast上的std::string (C风格的转换行为相同)。

如果我用显式的、非模板版本的转换操作符替换上面的代码,一切都很顺利:

代码语言:javascript
复制
class MyClass {
    int y;
public:
    MyClass(int v) : y(v) {}
    operator double() {return y;}
    operator float()  {return y;}
    operator int()    {return y;}
    operator std::string() {
        std::stringstream ss;
        ss << y << " bottles of beer.";
        return ss.str();
    }
};

我的std::string模板专门化有什么问题?为什么它只适用于初始化,而不适用于强制转换?

更新:

经过@luc-danton的一些模板魔法(我以前从未见过的元编程技巧),在启用实验性C++0x扩展之后,我让以下代码在g++ 4.4.5中工作。除了这里正在做的事情的恐怖之外,需要实验性的编译器选项本身就足以让而不是这样做。无论如何,希望这对其他人和对我一样有教育意义:

代码语言:javascript
复制
class MyClass {
    int y;
public:
    MyClass(int v) : y(v) {}

    operator std::string() { return "nobody"; }

    template <
        typename T
        , typename Decayed = typename std::decay<T>::type
        , typename NotUsed = typename std::enable_if<
            !std::is_same<const char*, Decayed>::value &&
            !std::is_same<std::allocator<char>, Decayed>::value &&
            !std::is_same<std::initializer_list<char>, Decayed>::value
          >::type
    >
    operator T() { return y; }
};

这显然迫使编译器为std::string选择转换operator std::string(),这克服了编译器遇到的任何歧义。

EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7741531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档