gpt4 book ai didi

c++ - 用于检测函数是否存在的 C++ 元函数问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:07:26 24 4
gpt4 key购买 nike

我遇到了一个我不理解的 C++ 元函数问题。我正在使用 C++14 编译 Apple 的 clang 8.1.0 版本。说明问题的工作代码如下。

我从其他地方抄袭了一个元功能,我正在尝试使用它。它旨在检测名为“bananify”的函数,这些函数具有传递给元函数的类型的参数。你称之为...

BananifyDetector<int>::value 

如果它可以看到形式声明的函数,它应该返回 true ...

bananify(int)

问题是,只有在 BananifyFinder 的模板定义之前声明要搜索的函数,而不是在它的实例化之前,它才有效。所以在我的示例代码中,我希望两者兼而有之,

BananifyFinder<int>
BananifyFinder<std::string>

使用下面的代码成功,但由于 bananify(std::string) 的定义位置,它失败了。

这令人沮丧,就好像我将函数检测器放在头文件中一样,我必须在客户端代码中包含顺序感知,这是一种极大的痛苦,并且在某些情况下可能无法正确处理。

我不确定这里发生了什么。它是 C++ 功能、clang 中的错误还是我做过的蠢事?

感谢任何帮助。

#include <iostream>
#include <type_traits>
////////////////////////////////////////////////////////////////////////////////
// A bananify function to be detected
// This is successfully found.
double bananify(int)
{
return 0.0;
}

/// A meta function that detects if a single argument function named 'bananify'
/// exists with takes an argument of the type passed to the metafunction.
///
/// Note, automatic casts will get in the way occasionally so if function
/// bananify(float) exists, a BananifyFinder<int>::value will return true.
template<class ARG1>
class BananifyFinder {
private :
template<typename ...> using VoidT_ = void;

template<typename A1, typename = void>
struct Test_ : std::false_type
{
typedef void returnType;
};

template<typename A1>
struct Test_<A1, VoidT_<decltype(bananify(std::declval<A1>()))>> : std::true_type
{
typedef decltype(bananify(std::declval<A1>())) returnType;
};

public :
typedef typename Test_<ARG1>::returnType returnType;
constexpr static bool value = Test_<ARG1>::value;
};

////////////////////////////////////////////////////////////////////////////////
// A bananify function to be detected that takes std::strings
// This fails to be found, but if we move it before the declaration of BananifyFinder it
// will be found;
std::string bananify(std::string)
{
return "s";
}

// dummy class with no bananify function to be found
class Nothing{};

// check the results of the metafunction 'T'
template<class T>
void CheckBanana(const std::string &str)
{
using DetectedType = BananifyFinder<T>;
std::cout << str << " detected is " << DetectedType::value << std::endl;
std::cout << str << " returns is " << typeid(typename DetectedType::returnType).name() << std::endl << std::endl;
}

////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
// this should print "BananifyFinder<int> 1 d"
CheckBanana<int>("BananifyFinder<int> ");

// this should print "BananifyFinder<std::string> 1 NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE"
// but it prints "BananifyFinder<std::string> 0 v"
// FAILS
CheckBanana<std::string>("BananifyFinder<std::string> ");

// this should print "BananifyFinder<Nothing> 0 v"
CheckBanana<Nothing>("BananifyFinder<Nothing> ");
}

最佳答案

模板分两个阶段进行解析。

在第一个中,解析独立于模板参数的表达式。在第二个中,依赖于模板的参数依赖项在Argument dependent lookup处被解析。执行。

decltype(bananify(std::declval<A1>()))>是参数依赖构造(取决于 A1 )。

来自 this page

And ADL examines function declarations with external linkage that are visible from both the template definition context and the template instantiation context (in other words, adding a new function declaration after template definition does not make it visible, except via ADL).

因此,您的代码会查看 std:: (使用 ADL)并且没有找到 bananify功能。

将其移动到模板实例化之前足以使其有资格进行查找。

关于c++ - 用于检测函数是否存在的 C++ 元函数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45838011/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com