通用模板阴影专业化

时间:2014-01-07 15:15:00

标签: c++11 template-specialization

我尝试了以下

template<class T>
T fromString(const String& str)
    {
    return toInt<T>(str.begin());
    }

template<>
inline
const String& fromString<const String&>(const String& str)
    {return str;}

template<>
inline
double fromString<double>(const String& str)
    {return toDouble(str.begin());}

template<>
inline
const char_t* fromString<const char_t*>(const String& str)
    {return str.begin();}

然而,似乎编译器试图调用第一个版本,它只适用于整数并具有显式实例化:

In function `Herbs::Stringbase<char16_t> Herbs::fromString<Herbs::Stringbase<char16_t> >(Herbs::Stringbase<char16_t> const&)':
...: undefined reference to `Herbs::Stringbase<char16_t> Herbs::toInt<Herbs::Stringbase<char16_t> >(char16_t const*)'

该函数就像这样调用

template<class T>
T itemFirstGet() const
    {return fromString<T>(m_items[0]);}

m_items是类中的字符串数组。

1 个答案:

答案 0 :(得分:1)

您可以将函数重载/特化委托给结构,并使一般情况不实现:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <type_traits>

namespace Detail {

    template<typename T, typename Enable = void> struct FromString;

    // Note: This could consume floating point types and more.
    template<typename T>
    struct FromString<T, typename std::enable_if<std::is_integral<T>::value>::type>
    {
        typedef T return_type;
        static return_type apply(const std::string& str) {
            std::istringstream s(str);
            return_type result;
            s >> result >> std::ws;
            if( ! s.eof())
                throw std::runtime_error("Invalid Integral Conversion");
            return result;
        }
    };

    template<>
    struct FromString<std::string>
    {
        typedef const std::string& return_type;
        static return_type apply(const std::string& str) {
            return str;
        }
    };
}

template<typename T>
inline typename Detail::FromString<T>::return_type
from_string(const std::string& str) {
    return Detail::FromString<T>::apply(str);
}

struct Unknown;

int main() {
    std::cout << from_string<int>("1") << ' ' << from_string<std::string>("Hello") << '\n';

    // error: no matching function for call to ‘from_string(const char [1])’
    // note: candidate is:
    // note: template<class T> typename Detail::FromString<T>::return_type from_string(const string&)
    // note:   template argument deduction/substitution failed:
    // In substitution of ‘template<class T> typename Detail::FromString<T>::return_type from_string(const string&) [with T = Unknown]’:
    // required from here
    // error: invalid use of incomplete type ‘struct Detail::FromString<Unknown, void>’
    // error: declaration of ‘struct Detail::FromString<Unknown, void>’

    // from_string<Unknown>("");

    // Exception
    from_string<int>("1 + 1");
}