1

我不确定如何提出这个问题,因为我对模板使用的了解很浅,但这里什么也没有。

我有一个类,我想为所有数值提供一个函数模板,然后这个函数模板调用需要 std::string 的非模板版本,如下所示。

template< class T > void
add_to_header( const std::string &key, const T &val )
{
    add_to_header( key, std::to_string( val ) );
}

virtual void
add_to_header( const header& header );

virtual void
add_to_header( const std::string &key, const std::string &val );

这段代码可以干净地编译,但我无法使用const char []进行调用。

instance.add_to_header( "Example1", 4 ); // successful
instance.add_to_header( "Example2", std::string( "str val" ) ); // successful
instance.add_to_header( "Example3", "Not fun" ); // error - none of the 9 overloads could convert all the argument types

解决这个问题的惯用方法是什么?

4

2 回答 2

7

如果您在声明中指定add_to_header它需要能够调用to_string其参数,则模板重载将通过 SFINAE 消除:

void add_to_header( const std::string &key, const std::string &val );

template<typename T> auto add_to_header( const std::string &key, const T &val )
-> decltype(std::to_string(val), void())  // uses comma operator
{
    add_to_header( key, std::to_string( val ) );
}

注意非模板重载需要在模板主体定义的句法点可见,这样主体内部的调用才能看到非模板重载。

使用 C++14 约束,我们可以将typename T(or class T) 替换为封装需求的约束:

template<typename T> constexpr bool ToStringable() {
    using namespace std;
    void to_string(...);
    return is_same<string, decltype(to_string(declval<T>()))>::value;
}

template<ToStringable T>
void add_to_header( const std::string &key, const T &val )
{
    add_to_header( key, std::to_string( val ) );
}
于 2013-05-16T15:41:33.100 回答
0

为什么要为此使用模板?你可以简单地重载 add_to_header 函数......

于 2013-05-16T15:43:01.900 回答