Почему поведение так отличается? #if 1
версия успешно (что странно) компилируется и производит ожидаемый вывод стандартный вывод, но версия с #if 0
не:
#include <iostream>
#include <type_traits>
#include <cstdlib>
template< typename T >
class X
{
struct B {};
public :
struct U : B {};
};
template< typename T >
struct Y
{
using X_type = X< T >;
template< typename D,
typename = typename std::enable_if< std::is_base_of< typename X_type::B, D >::value >::type >
void operator () (D const &) const
{
std::cout << "allowed only for derived from B" << std::endl;
}
};
template< typename T >
struct Z
{
using X_type = X< T >;
template< typename D >
auto
operator () (D const &) const
-> typename std::enable_if< std::is_base_of< typename X_type::B, D >::value >::type
{
std::cout << "allowed only for derived from B!" << std::endl;
}
};
int main()
{
using T = struct W; // not matters
using X_type = X< T >;
using U = typename X_type::U;
#if 0
using V = Y< T >;
#else
using V = Z< T >;
#endif
V v;
v(U());
return EXIT_SUCCESS;
}
Это генерирует ошибку (по существу «В» является частным в соответствии с моими ожиданиями (фактически) для обоих случаев):
<stdin>: In function 'int main()':
<stdin>:60:10: error: no match for call to '(V {aka Z<main()::W>}) (U)'
<stdin>:34:8: note: candidate is:
<stdin>:41:5: note: template<class D> typename std::enable_if<std::is_base_of<typename X<T>::B, D>::value>::type Z<T>::operator()(const D&) const [with D = D; T = main()::W]
<stdin>:41:5: note: template argument deduction/substitution failed:
<stdin>: In substitution of 'template<class D> typename std::enable_if<std::is_base_of<typename X<T>::B, D>::value>::type Z<T>::operator()(const D&) const [with D = D; T = main()::W] [with D = X<main()::W>::U]':
<stdin>:60:10: required from here
<stdin>:10:12: error: 'struct X<main()::W>::B' is private
<stdin>:41:5: error: within this context
g++ -v
вывод содержит следующую строку:
gcc version 4.8.1 (rev3, Built by MinGW-builds project)
Я ожидаю, что B
вообще недоступен из любого места, кроме X
,
Проблема возникает исключительно для шаблонов классов, но не для чистых классов (здесь у нас есть две идентичные проблемы, потому что оба варианта не нужно компилировать, но они компилируются).
Задача ещё не решена.
Других решений пока нет …