模板实例化上的SFINAE错误

SFINAE on template instantiation error?

本文关键字:SFINAE 错误 实例化      更新时间:2023-10-16

我问的可能是不可能的,但我会问只是为了确定。正如前面在这个问题中所问和回答的:SFINAE和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));

在Godbolt上玩代码。

谢谢!

这种尾随返回类型可以接受吗?

#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));

这对你有用吗?

#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));