3

我想为我的类型提供一个隐藏的朋友,同时在内联命名空间中还有另一个同名的对象。一切都适用于普通类型。

但是如果我有一个模板,当我实例化模板时编译器会出错

redefinition of 'cpo' as different kind of symbol

这是代码:

namespace lib{

    struct CPO{
        template<typename... T>
        constexpr decltype(auto) operator()(T&&... args) const{
            cpo(static_cast<T&&>(args)...);
        }
    };

    inline namespace cpo_impl_{
        inline constexpr CPO cpo{};
    }

    struct Foo1{
        friend auto cpo(Foo1){
            return 5;
        }
    };

    template <typename T>
    struct Foo2{
        friend auto cpo(Foo2){
            return 6;
        }
    };
}

int main(){
    lib::Foo1 f1{};
    lib::cpo(f1); // works fine;

    lib::Foo2<int> f2{}; // error here
}

较小的例子在这里

namespace lib{

    inline namespace impl_{
        inline constexpr int foo = 5;
    }

    template <typename T>
    struct Bar{
        friend auto foo(Bar){
            return 4;
        }
    };
}

int main(){
    lib::bar<int> b{};
}

顺便说一句,我知道其他技术,例如tag_invoke但在这里我无法控制名称和库

4

1 回答 1

3

您的代码格式正确。这是Clang 错误 37556

使用 -std=c++2a 编译这个格式良好的程序:

namespace X {
    inline namespace Y { int swap; }

    template<class>
    struct S {
        friend void swap(S&, S&) {}
    };
}

int main() {
    X::S<int> s1, s2;
    swap(s1, s2);
}

产生诊断(https://godbolt.org/g/ceWLxY):

<source>:6:21: error: redefinition of 'swap' as different kind of symbol
        friend void swap(S&, S&) {}
                    ^
<source>:11:15: note: in instantiation of template class 'X::S<int>' requested here
    X::S<int> s1, s2;
            ^
<source>:2:30: note: previous definition is here
    inline namespace Y { int swap; }
                            ^
1 error generated.

请注意,如果将 S 替换为非模板类​​,则程序编译成功。对 CWG 反射器的讨论验证了这个程序是格式良好的,包括 Richard 的声明“糟糕,Clang 在模板实例化情况下的重新声明检查是错误地执行重新声明查找,就像这里对限定名称一样,而不是重新声明查找不合格姓名。”

然而,没有修复的时间表。


作为一种解决方法,您可以Foo2自行包装inline namespace

inline namespace disambig_detail {
  template <typename T>
  struct Foo2{
    friend auto cpo(Foo2){
        return 6;
    }
  };
}

这应该足以改变声明区域以避免误诊。同时,名称查找应该与命名空间不存在的过程几乎相同。

于 2020-08-19T10:20:40.440 回答