如何在头文件中定义唯一类型以在多个翻译单元中使用并避免 ODR 错误?

问题描述 投票:0回答:1

在下面的示例中(可以使用 GCC 正常编译),我需要确保非静态成员

value1
value2
具有唯一的类型,并且一旦包含
struct Foo
的标头包含在多个 TU 中,它应该' t 导致 ODR 违规。我在链接阶段的项目中遇到了 ODR 错误,因为我在头文件中使用了
decltype( []{} )
,这意味着包含它的每个 TU 都将拥有自己唯一类型的 lambda。

因此我在这里使用

inline static
内部
struct Foo
来尝试解决这个问题。

最小的例子:

#include <type_traits>

// Util.hpp
template <typename UniqueType = decltype( []{} )>
inline constexpr UniqueType uniquely_typed_variable { UniqueType { } };

// Foo.hpp
struct Foo
{
    inline static constexpr auto unused_var1 { uniquely_typed_variable<> };
    inline static constexpr auto unused_var2 { uniquely_typed_variable<> };

    using MyType1 = decltype( unused_var1 );
    using MyType2 = decltype( unused_var2 );
    static_assert( not std::is_same_v<MyType1, MyType2> );

    MyType1 value1;
    MyType2 value2;
};


// A few .cpp files using "Foo.hpp"
// #include "Foo.hpp"

int main( )
{
    [[ maybe_unused ]] Foo foo {};
}

以上是正确的做法吗?或者是否有更优雅的方式来实现这种行为?

c++ lambda one-definition-rule variable-templates
1个回答
0
投票

解决方案:

#include <tuple>
#include <type_traits>


struct Foo
{
    inline static constexpr std::tuple uniquely_typed_values { []{}, []{} };

    using MyType1 = std::remove_reference_t<decltype( std::get<0>( uniquely_typed_values ) )>;
    using MyType2 = std::remove_reference_t<decltype( std::get<1>( uniquely_typed_values ) )>;
    static_assert( not std::is_same_v<MyType1, MyType2> );

    MyType1 value1;
    MyType2 value2;
};


int main( )
{
    [[ maybe_unused ]] Foo foo {};
}
© www.soinside.com 2019 - 2024. All rights reserved.