通过Boost';将c样式字符串自动解释为std::string;s属性树&x27;s.get函数

通过Boost';将c样式字符串自动解释为std::string;s属性树&x27;s.get函数,string,c++11,boost,boost-propertytree,String,C++11,Boost,Boost Propertytree,我使用boosts属性树,包括通过 #include "boost\property_tree\ptree.hpp" 而且。。。我想创建一个简单的函数,如果通过一个相当直接的模板函数找不到值,它将替换一个值: template <typename Type> Type getValueOrDefault( std::string const& str, Type defaultValue ) { Type returnValue = defaultValue;

我使用boosts属性树,包括通过

#include "boost\property_tree\ptree.hpp"
而且。。。我想创建一个简单的函数,如果通过一个相当直接的模板函数找不到值,它将替换一个值:

template <typename Type>
Type getValueOrDefault( std::string const& str, Type defaultValue )
{
    Type returnValue = defaultValue;

    try {
        returnValue = mSettings.get<Type>( str );
    }
    catch ( boost::property_tree::ptree_error &e )
    {
        // Log error!
    }

    return returnValue;
}
将导致以下错误:

boost\property_tree\stream_translator.hpp(36): error C2678: binary '>>' : no operator found which takes a left-hand operand of type 'std::basic_istream<char,std::char_traits<char>>' (or there is no acceptable conversion)

但我想知道是否有人知道我可以使用一些模板魔法来自动将c样式字符串解释为std::strings?

我找到的唯一方法是专门化
getValueOrDefault
const char*
,它使用
std::string
显式调用
getValueOrDefault

//Note that the return value is unspecified, it returns a 'const char*' to a temporary,
//which will be destroyed when the function returns
template <>
const char* getValueOrDefault(std::string const& str, const char* defaultValue)
{
    return getValueOrDefault<std::string>(str, defaultValue).c_str();
}
或者你可以直接重载函数(谢谢@m.s.)


您可以提供字符数组重载,该重载将字符数组转换为
std::string
,然后调用默认实现:

#include <iostream>
#include <string>

template <typename T>
T getValueOrDefault(const std::string& str, T&& defaultValue)
{
    std::cout << "inside default implementation" << std::endl;
    /* ... */
    return defaultValue;
}

template <std::size_t N>
std::string getValueOrDefault(const std::string& str, const char (&defaultValue)[N])
{
    std::cout << "inside char[] overload" << std::endl;
    return getValueOrDefault(str, std::string(defaultValue));
}


int main()
{
    auto x = getValueOrDefault("foo", "bar");
    return 0;
}
#包括
#包括
模板
T getValuerDefault(常量std::string&str,T&&defaultValue)
{

std::cout
const char*
重载不需要是模板,它可以是一个“常规”函数,返回
std::string
字符串文字
”s
需要C++14(与OP的C++11标记冲突)@m、 (谢谢:)但我还是保留文字作为选项,他没有明确提到C++14是被禁止的。我不记得有过这个问题,尽管我在心理上已经预料到了。由此我得出结论,Boost属性已经实现了相应的“DWIM”功能。您使用的是哪个版本的Boost?(从include路径拼写中,我得到了您使用MSVC的印象,哪个版本?)
//Note that the return value is unspecified, it returns a 'const char*' to a temporary,
//which will be destroyed when the function returns
template <>
const char* getValueOrDefault(std::string const& str, const char* defaultValue)
{
    return getValueOrDefault<std::string>(str, defaultValue).c_str();
}
//Default return type is the same as paramter
template <typename Type, typename Return = Type>
Return getValueOrDefault(std::string const& str, Type defaultValue)
{
    //...
}

//Trick the compiler to select this overload for 'const char*'
template <typename Return = std::string>
Return getValueOrDefault(std::string const& str, const char* defaultValue)
{
    return getValueOrDefault<std::string, std::string>(str, defaultValue);
}
//Overload for 'const char*'
std::string getValueOrDefault(std::string const& str, const char* defaultValue)
{
    return getValueOrDefault<std::string>(str, defaultValue);
}
//"c:/defaultdir/"s is a std::string (note the s after it => string literal)
getValueOrDefault("pathToImportantStuffParameter", "c:/defaultdir/"s);
#include <iostream>
#include <string>

template <typename T>
T getValueOrDefault(const std::string& str, T&& defaultValue)
{
    std::cout << "inside default implementation" << std::endl;
    /* ... */
    return defaultValue;
}

template <std::size_t N>
std::string getValueOrDefault(const std::string& str, const char (&defaultValue)[N])
{
    std::cout << "inside char[] overload" << std::endl;
    return getValueOrDefault(str, std::string(defaultValue));
}


int main()
{
    auto x = getValueOrDefault("foo", "bar");
    return 0;
}
#include <string>
#include <type_traits>

template <typename T>
struct return_type
{
    using type = T;
};

template <>
struct return_type<const char*>
{
    using type = std::string;
};

template <typename T>
using return_type_t = typename return_type<typename std::decay<T>::type>::type;

template <typename T>
return_type_t<T> getValueOrDefault(const std::string& str, T&& defaultValue)
{
    return_type_t<T> value(defaultValue);
    /* ... */
    return value;
}


int main()
{
    auto x = getValueOrDefault("foo", "bar");
    static_assert(std::is_same<decltype(x), std::string>::value, "");
    return 0;
}