SFINAE模板实例化错误?

时间:2016-04-04 04:03:11

标签: c++ templates c++14 template-meta-programming sfinae

我所要求的可能是不可能的,但我会要求确定。如前所述并在此问题中回答:SFINAE and decltype(auto),具有自动返回类型的函数可能不是SFINAE,因为扣除返回类型会导致模板实例化。在实例化期间,编译器将产生错误。

然而,也许有人知道一些疯狂的技巧将一段代码中的实例化错误转换为另一段代码中的替换失败,从而诱导SFINAE?

以下是一段代码,会导致错误:

#include <utility>

struct no_call_ops { };

struct caller
{
    // Goal is to detect whether a particular Handler type
    // will be ok to pass into caller
    template <typename Handler>
    auto operator() (Handler&& handler, int v)
    {
        handler(3.14);

        while (v--)
        {
            handler("hello world");
        }

        // etc...
        // more calls to handler that I don't want to
        // express in the trailing return type.
    }
};

struct fallback { };

struct tester
{
    // Would be nice if this fails substitution...
    template <typename Caller, typename Handler, typename... Args>
    auto operator() (Caller&& caller, Handler&& handler, Args&&... args)
        -> decltype(caller(handler, std::forward<Args>(args)...))
    { }

    fallback operator() (...) { return fallback{}; }  
};

// want detected_t to be "fallback"
using detected_t = decltype(tester{}(caller{}, no_call_ops{}, 42));

使用the code on Godbolt here

谢谢!

2 个答案:

答案 0 :(得分:0)

此尾随返回类型是否可接受?

#include <utility>
#include <functional>
using namespace std;

struct no_call_ops { };

template<class T>
using int_t = int;

struct caller
{
  template <typename Handler, int_t<typename result_of<Handler>::type> = 0>
  auto operator() (Handler&& handler, int) -> typename result_of<Handler>::type
  {
    handler(3.14);    
  }
};


struct fallback { };

struct tester
{
  template <typename Caller, typename Handler, typename... Args>
  auto operator() (Caller&& caller, Handler&& handler, Args&&... args) -> decltype(caller(handler, std::forward<Args>(args)...))
  { }

  fallback operator() (...) { return fallback{}; }  
};

using detected_t = decltype(tester{}(caller{}, no_call_ops{}, 42));

答案 1 :(得分:0)

这对你有用吗?

#include <utility>

struct no_call_ops { };

struct caller
{
  template <typename Handler, class = decltype( std::declval<Handler>()(3.14) )>
  decltype(auto) operator() (Handler&& handler, int)
  {
    handler(3.14);    
  }
};

struct fallback { };

struct tester
{
  template <typename Caller, typename Handler, typename... Args>
  auto operator() (Caller&& caller, Handler&& handler, Args&&... args) -> decltype(caller(handler, std::forward<Args>(args)...))
  { }

  fallback operator() (...) { return fallback{}; }  
};

using detected_t = decltype(tester{}(caller{}, no_call_ops{}, 42));