При написании небольшой библиотеки метапрограммирования шаблонов для личного использования я столкнулся с интересной проблемой.
Так как я повторно использовал несколько частных специализаций для некоторых метафайлов, я решил, что поместил бы их в общий шаблонный класс и использовал теги вместе с вложенной частичной специализацией, чтобы обеспечить различия в поведении.
Проблема в том, что я получаю бессмысленные (мне) результаты. Вот минимальный пример, демонстрирующий то, что я пытаюсь сделать:
#include <iostream>
#include <cxxabi.h>
#include <typeinfo>
template <typename T>
const char * type_name()
{
return abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
}
template <typename... Args>
struct vargs {};
namespace details
{
template <typename K>
struct outer
{
template <typename Arg>
struct inner
{
using result = Arg;
};
};
}
struct tag {};
namespace details
{
template <>
template <typename Arg, typename... Args>
struct outer<tag>::inner<vargs<Arg, Args...>>
{
using result = typename outer<tag>::inner<Arg>::result;
};
}
template <typename T>
using test_t = typename details::outer<tag>::inner<T>::result;
int main()
{
using t = test_t<vargs<char, int>>;
std::cout << type_name<t>() << '\n';
return 0;
}
Я получаю vargs<char, int>
в качестве вывода при использовании версии gmp и tag
версии 5.1.0 при использовании версии clang 3.6.0. Мое намерение состояло в том, чтобы вышеприведенный фрагмент кода напечатал char
, поэтому я довольно озадачен этими результатами.
Является ли вышеуказанная часть кода законной или она демонстрирует поведение undefined? Если это законно, каково ожидаемое поведение в соответствии со стандартом?