Странное поведение при разборе _Atomi c с шаблонами - PullRequest
0 голосов
/ 12 января 2020
//clang 3.8.0

#include <iostream>

template<typename T>
_Atomic T* get_atomic(T* val) {
    return reinterpret_cast<_Atomic T*>(val);
}

int main()
{

    volatile int val = 1;
    _Atomic volatile int* val_ptr = reinterpret_cast<_Atomic volatile int*>(&val);
    // works as expected
    std::cout << *val_ptr;
    // Fails due to "_Atomic cannot be applied to qualified type 'volatile int'"
    //std::cout << "Hello, world!\n" << *get_atomic(&val);
}

Почему существует несоответствие между способом анализа расширения шаблона и способом анализа явного расширения? Они должны быть идентичны. Есть ли способ убедиться, что _Atomi c рассматривается как квалификатор при наличии аргументов шаблона?

Ответы [ 2 ]

1 голос
/ 13 января 2020

Ключевое слово _Atomic происходит от C (C11) и не является ключевым словом в C ++. В C ++ атомы указываются через std::atomic. Лучше всего не смешивать синтаксические понятия двух языков.

Если вам нужно смешать код, который обращается к данным atomi c с обоих языков, вам следует иметь дело с типами atomi c, такими как std::atomic_int, или придумайте некоторые макроинтерфейсы, подобные следующим

#ifdef __cplusplus
#define myAtomic(T) std::atomic< T >
#else
#define myAtomic(T) _Atomic(T)
#endif

На любой разумной платформе они должны быть двоично-совместимыми.

0 голосов
/ 12 января 2020

Это похоже на ошибку либо в spe c, либо в clang. Чтобы обойти это, вы можете использовать следующую уловку для восстановления классификаторов исходного типа:

//clang 3.8.0

#include <iostream>

template<typename T>
struct Impl {
    T __a_value;
    using underlying_t = T;
    Impl(T val) : __a_value(val) {}
};

template <typename Tp_, typename Original_>                                                                                        
struct __annotate_with_qualifiers {                                                                                                 
  using __const_qualified = typename std::conditional<std::is_const<Original_>::value, const Tp_, Tp_>::type;                                 
  using __type = typename std::conditional<std::is_volatile<Original_>::value, volatile __const_qualified, __const_qualified>::type;          
};                                                                                                                                  

template<typename _Tp>                     
_LIBCPP_INLINE_VISIBILITY inline                                                                                                    
typename __annotate_with_qualifiers<_Atomic(typename _Tp::underlying_t), _Tp>::__type*            
__cxx_atomic_pointer_to_data(_Tp* __value) {                                                                                        
  return reinterpret_cast<typename __annotate_with_qualifiers<_Atomic(typename _Tp::underlying_t), _Tp>::__type*>(&__value->__a_value);                                                                                                       
}

template<typename T>
void print_val(const volatile T* val) {
    std::cout << "Const volatile " << *val << std::endl;
}

template<typename T>
void print_val(const T* val) {
    std::cout << "Const " << *val << std::endl;
}

template<typename T>
void print_val(volatile T* val) {
    std::cout << "Volatile " << *val << std::endl;
}

template<typename T>
void print_val(T* val) {
    std::cout << "Plain " << *val << std::endl;
}

int main()
{
    Impl<int> val(1);
    volatile Impl<int> val2(2);
    const Impl<int> val3(3);
    const volatile Impl<int> val4(4);
    print_val(__cxx_atomic_pointer_to_data(&val));
    print_val(__cxx_atomic_pointer_to_data(&val2));
    print_val(__cxx_atomic_pointer_to_data(&val3));
    print_val(__cxx_atomic_pointer_to_data(&val4));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...