I repeat the code from the previous question to make this question self-contained. The code below compiles and does not issue any warnings if it is compiled using gcc 4.8.3. with -std=c++1y
. However, it does issue warnings if compiled with -std=c++0x
flag. In the context of the previous question it was stated that the code does not compile using gcc 4.9.0. Unfortunately, at present, I do not fully understand how auto
is implemented. Thus, I would appreciate if anyone could answer the following questions:
1). Is the code below valid C++ with respect to the C++14 standard?
2). If yes, would this code be considered a good style? If not, why not?
3). Why does the code below compile and work (sometimes) when using C++11 compilers? Alternatively, why does it not always work? Are there any specific flags/options/settings that could prevent it from working?
template<int N> auto getOutputPort2();
template<> auto getOutputPort2<0>();
template<> auto getOutputPort2<1>();
template<>
auto getOutputPort2<0>()
{
return std::unique_ptr<int>(new int(10));
}
template<>
auto getOutputPort2<1>()
{
return std::unique_ptr<string>(new string("qwerty"));
}
Yes, as far as I can tell. It's sometimes a bit hard to prove, since often there's simply nothing forbidding it. However, we can look at an example in a recent draft (post-N4296), [dcl.spec.auto]/13:
The same paragraph specifies:
So the explicit specializations of a function template must use return type deduction. I cannot find anything that forbids different return types for different specializations. Similarly, in C++98, different return types for function template specializations (of the same primary template) can be achieved by making the return type dependent on the template arguments. By using metaprogramming, you can basically achieve the same as when using return type deduction to specify unrelated return types for the different specializations.
The code in the OP is ill-formed in C++11. Return type deduction for ordinary functions (non-lamdas) is a feature introduced in C++14. A program that contains this code snippet is ill-formed. However, the Standard does not mandate that implementations (compilers) must reject ill-formed programs. It merely states in [intro.compliance]/2.2:
and in /8
(So implementations can accept this program as an extension.)
g++4.8.3 issues a warning, which counts as a diagnostic message. g++4.9 issues an error, which is also a diagnostic message. Both are compliant. By specifying
-Werror
, you could tell a g++4.8.3 to reject this program. (You'd have to ask the gcc developers why they've changed that from a warning to an error.)