C++ 无限模板递归,因为没有bool表达式优化,仅使用gcc

C++ 无限模板递归,因为没有bool表达式优化,仅使用gcc,c++,templates,gcc,sfinae,enable-if,C++,Templates,Gcc,Sfinae,Enable If,我在做一个词法播音员。请参见下面代码中简化的、有问题的部分。该代码使用clang和msvc编译,但无法使用gcc编译。似乎,在lexicalCast的std::enable_的第一个参数中,如果gcc尝试在计算bool表达式之前计算它的所有操作数,而clang和msvc进行优化,并忽略LexicalCastable::value的计算,如果std::is_相同表达式失败。 我的问题是: 标准是否规定了哪些行为是正确的 我如何解决这个问题,才能用GCC编译这段代码 代码: #包括 #包括 模板

我在做一个词法播音员。请参见下面代码中简化的、有问题的部分。该代码使用clang和msvc编译,但无法使用gcc编译。似乎,在lexicalCast的
std::enable_的第一个参数中,如果
gcc尝试在计算bool表达式之前计算它的所有操作数,而clang和msvc进行优化,并忽略
LexicalCastable::value
的计算,如果
std::is_相同
表达式失败。 我的问题是:

  • 标准是否规定了哪些行为是正确的
  • 我如何解决这个问题,才能用GCC编译这段代码
代码:

#包括
#包括
模板
类词汇表;
模板类型名
std::启用_if<
!std::值是否相同
&& !std::值是否相同
&&LexicalCastable::value
&&LexicalCastable::value,
至>::键入lexicalCast(const From和From){
返回lexicalCast(lexicalCast(from));
}
模板
类LexicalCastable
{
模板
静态自动测试(int)
->decltype(lexicalCast(std::declval()),std::true_type{});
模板
静态自动测试(…)->std::false_类型;
公众:
静态常量布尔值=decltype(测试(0))::值;
};
静态断言(!LexicalCastable::value,“”);
gcc的错误:

prog.cpp: In substitution of ‘template<class TT> static decltype ((lexicalCast<TT>(declval<From>()), std::true_type{})) LexicalCastable<From, To>::test(int) [with TT = std::__cxx11::basic_string<char>]’:
prog.cpp:35:45:   required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3:   required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:29:30:   required by substitution of ‘template<class TT> static decltype ((lexicalCast<TT>(declval<From>()), std::true_type{})) LexicalCastable<From, To>::test(int) [with TT = std::__cxx11::basic_string<char>]’
prog.cpp:35:45:   required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3:   required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:29:30:   [ skipping 889 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
prog.cpp:35:45:   required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3:   required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:29:30:   required by substitution of ‘template<class TT> static decltype ((lexicalCast<TT>(declval<From>()), std::true_type{})) LexicalCastable<From, To>::test(int) [with TT = std::__cxx11::basic_string<char>]’
prog.cpp:35:45:   required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3:   required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:40:43:   required from here
prog.cpp:29:49: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
   -> decltype(lexicalCast<TT>(std::declval<From>()), std::true_type{});
                               ~~~~~~~~~~~~~~~~~~^~
prog.cpp:替换“模板静态decltype((lexicalCast(declval()),std::true_type{}))LexicalCastable::test(int)[使用TT=std::_cxx11::basic_string]:
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
prog.cpp:29:30:替换“模板静态decltype((lexicalCast(declval()),std::true_type{}))LexicalCastable::test(int)[带TT=std::_cxx11::basic_string]时需要”
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
prog.cpp:29:30:[跳过889实例化上下文,使用-ftemplate backtrace limit=0禁用]
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
prog.cpp:29:30:替换“模板静态decltype((lexicalCast(declval()),std::true_type{}))LexicalCastable::test(int)[带TT=std::_cxx11::basic_string]时需要”
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
进度cpp:40:43:从这里开始需要
prog.cpp:29:49:致命错误:模板实例化深度超过最大值900(使用-ftemplate depth=增加最大值)
->decltype(lexicalCast(std::declval()),std::true_type{});
~~~~~~~~~~~~~~~~~~^~
如何解决这个问题,使之能够用GCC编译此代码

您可以使用保证短路的
std::conjunction
(C++17)

template <typename To, typename From>
typename std::enable_if<
    std::conjunction<
           std::negation<std::is_same<std::string, To>>,
           std::negation<std::is_same<std::string, From>>,
           LexicalCastable<From, std::string>
           LexicalCastable<std::string, To>>::value,
    To>::type
lexicalCast(const From &from)
{
    return lexicalCast<To>(lexicalCast<std::string>(from));
}
模板
typename std::启用\u如果<
连词<
否定,
否定,
词汇表
LexicalCastable>::值,
至>::键入
lexicalCast(常量自和自)
{
返回lexicalCast(lexicalCast(from));
}
template <typename To, typename From>
typename std::enable_if<
    std::conjunction<
           std::negation<std::is_same<std::string, To>>,
           std::negation<std::is_same<std::string, From>>,
           LexicalCastable<From, std::string>
           LexicalCastable<std::string, To>>::value,
    To>::type
lexicalCast(const From &from)
{
    return lexicalCast<To>(lexicalCast<std::string>(from));
}