【问题标题】:How to make a function template only works for types in a particular namespace?如何使函数模板仅适用于特定命名空间中的类型?
【发布时间】:2017-03-19 06:36:08
【问题描述】:

我有一个命名空间my_space 并将函数模板定义为

namespace my_space
{
    template<class T>
    ostream operator<<(ostream& os, T const& t)
    { ... }
}

我希望这个函数只适用于我在my_space 中的类,或者它可能对不在my_space 中的某些类型变得模棱两可。例如

namespace my_space
{
     void f()
     {
           cout << "test"; //overload ambiguous
      }
}

有什么办法可以避免吗?

【问题讨论】:

  • 对于不在my_space 中的类型,如果你写other_type ot; std::cout &lt;&lt; ot; 之类的东西,你的函数将不会被使用。够了吗?
  • 查看示例
  • 简短的回答是不要在你的命名空间中重载这样的运算符。照原样,您的代码会导致歧义,因为它依赖于using namespace std 的生效。完全消除这种依赖(即在您的命名空间中将ostream 完全指定为std::ostream)。此外,与 std::ostream 一起使用的 operator&lt;&lt;() 函数返回一个引用 - 按值返回保证您的代码不会编译。
  • 这里打错,在原代码中使用std::。
  • @user1899020 我还是听不懂你的问题;这是模棱两可的。 rextester.com/JRGB3285

标签: c++ c++11 templates namespaces


【解决方案1】:

我们可以用一点 ADL(参数依赖查找)和一个辅助函数来做到这一点。

在这种情况下,我们使用namespace_test_helper,并让它返回true_type,当且仅当查询的类型(或其依赖类型)来自my_namespace

namespace support {
  template<class...Ts>
  constexpr std::false_type namespace_test_helper( Ts&&... ) { return {}; }
  template<class T>
  constexpr auto namespace_test( T&& t ) {
    return namespace_test_helper( std::forward<T>(t));
  }

}
namespace my_namespace {
  template<class T>
  constexpr std::true_type namespace_test_helper( T&& ) { return {}; }
  template<class T,
    class=std::enable_if_t<decltype(::support::namespace_test( std::declval<T>() )){}>
   >
  std::ostream& operator<<( std::ostream& os, T const& t ) {
    return os << "my <<";
  }
  enum bob {};
  void test() {
      std::cout << "hello world\n";
      std::cout << bob{} << "\n";
  }
}

int main() {
    ::my_namespace::test();
    std::cout << ::my_namespace::bob{} << "\n";
}

请注意,my_namespace 中带有模板参数的类型也可以找到它。

我们可以将其扩展到检测某些名称空间中的哪一个;但是您必须为每个这样的命名空间定义一个不同的类型。 std::integral_constant&lt;std::size_t, I&gt; 可以工作,但您负责为每个命名空间设置唯一的 I

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    • 1970-01-01
    • 2012-09-16
    • 2021-08-12
    相关资源
    最近更新 更多