请考虑以下代码段:
#include <type_traits>
#include <string>
template<typename T>
std::string stringify (const T& value)
{ return "dummy"; }
template<typename T>
class foo_class
{
public:
template<typename Converter = std::string(&)(const T&),
class = typename std::enable_if<std::is_convertible<
typename std::result_of<Converter(const T&)>::type,
std::string>
::value>::type>
foo_class(const T &value, const Converter &converter = stringify<T>) {}
};
int main(int,const char*[])
{
int X = 7;
foo_class<int> x(X);
foo_class<int> y(X, stringify<int>);
}
第一个构造函数编译得很好,但是第二个构造函数在Clang 3.6.2下失败并出现以下错误:
candidate template ignored: substitution failure [with Converter = std::__cxx11::basic_string<char> (const int &)]: function cannot return function type 'std::__cxx11::basic_string<char> (const int &)'
foo_class(const T &value, const Converter &converter = stringify<T>) {}
我通过在参数列表中将const Converter &
更改为Converter
来找到一种方法来修复它,尽管在某些情况下这可能不是理想的行为。
错误是由std :: enable_if&lt; ..&gt;中的某些内容引起的条款。我可以删除它,代码编译(并运行)就好了。
我主要对这个问题感兴趣&#34;为什么&#34; - 为什么它在第一种情况下工作(当选择函数作为默认参数时),但在第二种情况下,当显式选择它时不工作。
作为第二个问题,什么被认为是解决问题的最佳方式?我的意思是,我有一个解决方法,但更喜欢坚持使用&#34; const引用默认情况下#34;参数的政策不是函数。
答案 0 :(得分:1)
这不是你应该如何使用result_of
。
它应该始终与引用一起使用,其中引用的类型指定要知道其结果的调用中相应表达式的值类别。
因此,如果您将converter
称为const
左值,那么您需要result_of<const Converter &(const T&)>
。还有一些例子:
// forward the value category of the function object
template<class F>
auto f(F&& f) -> std::result_of_t<F&&()> { return std::forward<F>(f)(); }
// always call as an lvalue, accept both lvalue and rvalue function object
template<class F>
auto f(F&& f) -> std::result_of_t<F&()> { return f(); }
// Accept everything by value, but call with all lvalues
template<class F, class... Args>
auto f(F f, Args... args) -> std::result_of_t<F&(Args&...)> { return f(args...); }
// Accept everything by value, and move them all
template<class F, class... Args>
auto f(F f, Args... args) -> std::result_of_t<F&&(Args&&...)> { return std::move(f)(std::move(args)...); }
答案 1 :(得分:0)
在你的第二个片段中,你有
Converter = std::string(const T&) // without reference
2种可能的修复/解决方法:
使用std::decay_t
template<typename T>
class foo_class
{
public:
template<typename Converter = std::string(&)(const T&),
std::enable_if_t<
std::is_convertible<
std::result_of_t<std::decay_t<Converter>(const T&)>,
std::string>::value>* = nullptr>
foo_class(const T &value, const Converter &converter = stringify<T>) {}
};
或使用
foo_class<int> y(X, &stringfy<int>);