Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SFINAE:检测是否存在需要显式专门化的模板函数_C++_Templates_C++11_Sfinae_Explicit Specialization - Fatal编程技术网

C++ SFINAE:检测是否存在需要显式专门化的模板函数

C++ SFINAE:检测是否存在需要显式专门化的模板函数,c++,templates,c++11,sfinae,explicit-specialization,C++,Templates,C++11,Sfinae,Explicit Specialization,作为后续,我尝试检测是否存在需要显式专门化的模板函数 我当前的工作代码检测非模板函数(多亏了DyP的帮助),前提是它们至少接受一个参数,以便可以使用依赖名称查找: // switch to 0 to test the other case #define ENABLE_FOO_BAR 1 namespace foo { #if ENABLE_FOO_BAR int bar(int); #endif } namespace feature_test { namespace

作为后续,我尝试检测是否存在需要显式专门化的模板函数

我当前的工作代码检测非模板函数(多亏了DyP的帮助),前提是它们至少接受一个参数,以便可以使用依赖名称查找:

// switch to 0 to test the other case
#define ENABLE_FOO_BAR 1

namespace foo {
  #if ENABLE_FOO_BAR
    int bar(int);
  #endif
}

namespace feature_test {
  namespace detail {
    using namespace foo;
    template<typename T> decltype(bar(std::declval<T>())) test(int);
    template<typename> void test(...);
  }
  static constexpr bool has_foo_bar = std::is_same<decltype(detail::test<int>(0)), int>::value;
  static_assert(has_foo_bar == ENABLE_FOO_BAR, "something went wrong");
}

但是,当我尝试检测需要显式专门化的模板函数时,当
foo::bar()
存在时,
static\u assert
将启动

namespace foo {
  #if ENABLE_FOO_BAR
    template<typename T, typename U> T bar(U);
  #endif
}

//...
// error: static assertion failed: something went wrong
error: ‘bar’ was not declared in this scope
     template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
                                   ^
error: expected primary-expression before ‘int’
     template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
                                       ^
// lots of meaningless errors that derive from the first two
foo::bar()
存在时(该函数被正确检测到),这项功能可以正常工作,但现在当
foo::bar()
不存在时,所有的麻烦都会发生

namespace foo {
  #if ENABLE_FOO_BAR
    template<typename T, typename U> T bar(U);
  #endif
}

//...
// error: static assertion failed: something went wrong
error: ‘bar’ was not declared in this scope
     template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
                                   ^
error: expected primary-expression before ‘int’
     template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
                                       ^
// lots of meaningless errors that derive from the first two
错误:未在此范围内声明“bar”
模板decltype(bar(std::declval()))测试(int);
^
错误:“int”之前应为主表达式
模板decltype(bar(std::declval()))测试(int);
^
//许多无意义的错误源于前两个
似乎我的显式专门化尝试失败了,因为编译器不知道
bar
是一个模板


我将省去我试图解决这个问题的一切,直截了当地说:如何检测函数的存在,例如
template T bar(U)

以下内容可能会帮助您:

// Helper macro to create traits to check if function exist.
// Note: template funcName should exist, see below for a work around.
#define HAS_TEMPLATED_FUNC(traitsName, funcName, Prototype)                          \
    template<typename U>                                                             \
    class traitsName                                                                 \
    {                                                                                \
        typedef std::uint8_t yes;                                                    \
        typedef std::uint16_t no;                                                    \
        template <typename T, T> struct type_check;                                  \
        template <typename T = U> static yes &chk(type_check<Prototype, &funcName>*); \
        template <typename > static no &chk(...);                                    \
    public:                                                                          \
        static bool const value = sizeof(chk<U>(0)) == sizeof(yes);                  \
    }
检查是否存在barbar2的代码

//不应使用的伪类
名称空间详细信息{
结构虚拟;
}
//把戏,这样名字就存在了。
//我们使用了一种永远不会发生的专门化
名称空间foo{
模板
std::在条形图(U)中启用_;
模板
std::如果bar2(U)启用_;
}
#在宏中定义逗号//技巧以便能够使用“,”
//创造特质
HAS_TEMPLATED_FUNC(HAS_foo_bar,foo::bar,int(*)(int));
HAS_TEMPLATED_FUNC(HAS_foo_bar2,foo::bar2,int(*)(int));
//测试它们
static_assert(has_foo_bar::value,“出错了”);
static_assert(!has_foo_bar2::value,“出错了”);

我不确定这是否有助于解决您的问题,但我知道检查接口的方法是尝试实例化某些预期函数(静态或成员)的函数指针,然后首先在那里编译失败。我不知道它是否适用于名称空间全局函数。我的第一种方法依赖于本文中提出的建议,我认为这里使用的一些机制可以使用一些STL SFINAE Asserter进行替换,但原则仍然适用。@g-makulik不幸的是,您的链接已断开。但我想我明白你的意思,我会尝试一些方法,如果成功,我会报告。对不起,我只是从我的一个标题引用中复制了它,是的,它显然不再可用。我在这里找到了一个文档的有效链接(至少对我来说是这样):很棘手。如果我能为某种类型的
静态
方法解决它,那就足够了吗?因为在那里我们可以使方法依赖,然后使用
template
关键字强制
template
解析。@g-makulik我认为你在链接的论文中是对的,这可能不适用于我在这里描述的情况。尽管我仍在试图充分理解它,但由于它涉及到我感兴趣的另一个主题(概念),因此很难正确区分手头的问题。简言之:我真的被这一切弄糊涂了,在一个星期六的晚上,这对我可怜的大脑来说是太多的信息了(
// namespace to test
namespace foo {
    template<typename T, typename U> T bar(U);
    // bar2 not present
}
// dummy class which should be never used
namespace detail {
    struct dummy;
}

// Trick, so the names exist.
// we use a specialization which should never happen
namespace foo {
    template <typename T, typename U>
    std::enable_if<std::is_same<detail::dummy, T>::value, T> bar(U);

    template <typename T, typename U>
    std::enable_if<std::is_same<detail::dummy, T>::value, T> bar2(U);
}

#define COMMA_ , // trick to be able to use ',' in macro

// Create the traits
HAS_TEMPLATED_FUNC(has_foo_bar, foo::bar<T COMMA_ int>, int(*)(int));
HAS_TEMPLATED_FUNC(has_foo_bar2, foo::bar2<T COMMA_ int>, int(*)(int));

// test them
static_assert(has_foo_bar<int>::value, "something went wrong");
static_assert(!has_foo_bar2<int>::value, "something went wrong");