如何处理void decltype();



我想创建一个模板,该模板调用另一个对象的成员函数,该对象返回与成员函数相同的类型。在成员函数上使用decltype的语法有点难看,但除了一种情况外,它似乎在所有情况下都有效。

电话:

struct container: map<string, C> 
{
    template< typename MemFnPtrType, typename... _ArgTypes>
    auto safeOperation(string key, MemFnPtrType mfp, _ArgTypes&&... args )
        -> decltype( (((C*)nullptr)->*mfp)(args...))
    {
        C* pC = NULL;
        decltype((pC->*mfp)(args...)) result;
        iterator it = find(key);
        if (it != end())
        {
            C* pC = &(it->second);
            result = (pC->*mfp)(args...);
            cout << "result:" << result << "n";
        }
        else
        {
            cout << "key: " << key << " missingn";
        }
        return result;
    }
};

在成员函数返回void之前可以正常工作。

是否有一种方法可以检测到这一点并删除违规行?

我显然可以创建一个voidSafeOperation函数。我不介意创建另一个模板,但我想使用相同的名称"safeOperation",因此调用站点不需要根据成员函数的返回类型使用不同的帮助程序。

谢谢!

完整的示例:http://cpp.sh/7ft

不幸的是,我认为你被困在这里,不得不对返回类型进行SFINAE。从一个类型trait开始(这比你的decltype表达式干净多了)

template <typename MF, typename... Args>
using Res = typename std::result_of<MF(C, Args...)>::type;

然后切换到

template <typename MF, typename... Args>
typename std::enable_if<
    std::is_same<Res<MF, Args...>, void>::value
>::type safeOperation(string key, MF mfp, Args... args)
{
     /* void case */
}
template <typename MF, typename... Args>
typename std::enable_if<
    !std::is_same<Res<MF, Args...>, void>::value,
    Res<MF, Args...>
>::type safeOperation(string key, MF mfp, Args... args)
{
     /* non-void case */
}

或者您可以在is_void上标记调度:

template <typename MF, typename... Args>
Res<MF, Args...> safeOperation(string key, MF mfp, Args... args)
{
    return safeOperation(std::is_void<Res<MF, Args...>>{},
                         key, mfp, args...);
}

:

template <typename MF, typename... Args>
void safeOperation(std::true_type /* void */, 
                   string key, MF mfp, Args... args) 
{ .. }
template <typename MF, typename... Args>
Res<MF, Args...> safeOperation(std::false_type /* non-void */, 
                               string key, MF mfp, Args... args) 
{ .. }

这是一个特例。autodecltype的尾随返回类型不能用于void的返回类型,因为void是一个不完全类型。

的例子:

auto nothingMuch()
{
    return;
}
// nope
//decltype(void {}) nothingMuchEither()
//{
//  return;
//}
// nope
//auto noTrailing() -> decltype(void {})
//{
//
//}
// always works
decltype(auto) nothing()
{
    return;
}
auto main() -> decltype(int {})
{
    nothing();
    nothingMuch();
    return 0;
}

最简单的修复方法是将末尾返回类型中的autodecltype替换为decltype(auto)作为返回类型(需要c++ 14)

相关内容

最新更新