简体   繁体   English

确定“通用函数”的返回类型

[英]Determining return type of “generic function”

Suppose, I want to develop a generic library which should be usable with number-like types including double and user-defined types. 假设,我想开发一个通用库,它应该可以用于类似数字的类型,包括双重和用户定义的类型。 The problem, I'm facing right now is that I don't know how to write the return type of a function template much like this one: 我现在面临的问题是,我不知道如何编写函数模板的返回类型,就像这样:

template<class T>
auto transmogrify(T x)
-> ???
{
    using std::abs;
    return abs(x)+2.0;
}

The using declaration makes this function template's body work for primitive types because these don't have an associated namespace (and hence, there is no ADL). using声明使这个函数模板的主体适用于原始类型,因为它们没有关联的命名空间(因此没有ADL)。 But I want transmogrify to use specialized abs functions in case the author of a user-defined type provides his own abs function. 但是我希望transmogrify使用专门的abs函数,以防用户定义类型的作者提供自己的abs函数。 I can't simply use 我不能简单地使用

-> decltype( abs(x)+2.0 )

because this would not work for, say, doubles since std::abs is not in scope (as far as I can tell). 因为这不适用于比赛,因为std :: abs不在范围内(据我所知)。 But writing 但写作

-> decltype( std::abs(x)+2.0 )

would disable ADL. 会禁用ADL。 But disabling ADL is not an option. 但禁用ADL不是一种选择。 Also, the value returned by a specialized abs function might not be of type T but some other type. 此外,专用abs函数返回的值可能不是T类型,而是某些其他类型。

Any ideas on how to solve the return type issue while (a) keeping ADL and (b) falling back on some default function (like std::abs in this case) for types that don't provide a specialized abs. 关于如何解决返回类型问题的任何想法,同时(a)保持ADL和(b)回退到某些默认函数(如本例中的std :: abs),对于不提供专用abs的类型。

Use a separate namespace, where you can put the using clause. 使用单独的命名空间,您可以在其中放置using子句。 This prevents the namespace pollution, since the using clause only applies to that namespace. 这可以防止命名空间污染,因为using子句仅适用于该命名空间。 I would recommend naming it something unique, so you don't accidentally spread it around. 我建议将它命名为独特的东西,这样你就不会意外地将它传播开来。

namespace transmog_detail
{
   using std::abs;

   template<class T>
   auto transmogrify(T x) -> decltype(abs(x) + 2.0)
   {
      return abs(x) + 2.0;
   }
}

// Then pull it into the current namespace, as recommended by @LucDanton.
using transmog_detail::transmogrify;

// Or if there is a reason, you can forward. 
// template<class T>
// auto transmogrify(T x)
// -> decltype(transmog_detail::transmogrify(x))
// {
//    return transmog_detail::transmogrify(x);
// }

The above answers are good, but the simoplest way i can think of is to use the typeinfo header. 上面的答案很好,但我能想到的最简单的方法是使用typeinfo标题。 it was specifically designed to determine types and constructors of objects. 它专门用于确定对象的类型和构造函数。

see here: http://www.cplusplus.com/reference/std/typeinfo/type_info/ 见这里: http//www.cplusplus.com/reference/std/typeinfo/type_info/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM