2015-08-24 4 views
16

У меня есть шаблонный шаблон A и шаблонная функция f, которая возвращает A объектов. Я хочу f<T> быть другим A<T> и по-прежнему constexprОбъявление специалиста constexpr как друга

template <typename T> 
class A; 

template <typename T> 
constexpr A<T> f(); 

//f<T> is a friend of A<T> 

template <typename T> 
class A { 
    friend /* constexpr? */ A f<T>(); 
    constexpr A() {} 
}; 

template <typename T> 
constexpr A<T> f() { return {}; } 

int main() { 
    constexpr auto a = f<void>(); 
} 

Я не могу получить лязг и GCC, чтобы договориться о том, что прямо здесь. Если я не ставлю constexpr в другом заявлении, НКУ работает нормально, но лязг не будет компилировать его, erroring с:

main.cpp:18:18: error: constexpr variable 'a' must be initialized by a constant expression 
    constexpr auto a = f<void>(); 
       ^ ~~~~~~~~~ 
main.cpp:18:23: note: non-constexpr function 'f<void>' cannot be used in a constant expression 
    constexpr auto a = f<void>(); 
        ^
main.cpp:9:12: note: declared here 
    friend A f<T>(); 

Если я пометить его как constexpr в другом заявлении, лязг отлично компилируется, но НКУ дает me error:

main.cpp:9:27: error: 'constexpr' is not allowed in declaration of friend template specialization 'A<T> f<T>()' 
    friend constexpr A f<T>(); 

Как я могу сделать всех счастливыми?

+0

см. [Этот вопрос и ответы] (http://stackoverflow.com/questions/29871138/constexpr-is-not-allowed-in-declaration-of-friend-template-specialization) для аналогичной ошибки – TemplateRex

ответ

6
int main() { constexpr auto a = f<void>(); } 

Это специализируется на шаблон функции f как функции f<void>(); во время специализации f компилятор также пытается создать экземпляр A<void>, который, в свою очередь, объявляет специализацию friend f<void>().

Эти два заявления MUST матч за constexpr:

[dcl.constexpr]/1

[...] If any declaration of a function or function template has a constexpr specifier, then all its declarations shall contain the constexpr specifier. [Note: An explicit specialization can differ from the template declaration with respect to the constexpr specifier. —end note]

Clang, вероятно, следует erroring ранее, когда вы опускаете constexpr в friend декларации, а не штамповкой что, как представляется, является функцией не constexpr, но, по крайней мере, она принимает правильный синтаксис.

Gcc не должен допускать, чтобы версия отсутствовала constexpr и выдавала сообщение об ошибке constexpr из-за bug. С тех пор это исправлено в багажнике, и я могу подтвердить, что он работает сейчас, хотя он все еще не дает ошибку, когда отсутствует constexpr.

Смежные вопросы